使用 WHILE 循环而不是 FOR 循环重命名文件

使用 WHILE 循环而不是 FOR 循环重命名文件

考虑一下我们有很多照片的名称如DSC_20170506_170809.JPEG。为了重命名照片以使它们遵循模式Paris_20170506_170809.JPEG,我编写了以下完美运行的脚本。

for file in *.JPEG; do mv ${file} ${file/DSC/Paris}; done

我的问题是,我们如何使用循环while而不是for循环来编写这个脚本?

答案1

这里使用循环没有任何问题while。你只需要做对:

set -- *.jpeg
while (($#)); do
mv -- "${1}" "${1/DSC/Paris}"
shift
done

上面的循环while与循环一样可靠for(它将适用于任何文件名),虽然后者在许多情况下是最合适使用的工具,但前者是一个有效的替代方案1,有其用途(例如上面可以一次处理三个文件或仅处理一定数量的参数等)。


所有这些命令(setwhile..do..doneshift)都记录在 shell 手册中,并且它们的名称是不言自明的......

set -- *.jpeg
# set the positional arguments, i.e. whatever that *.jpeg glob expands to

while (($#)); do
# execute the 'do...' as long as the 'while condition' returns a zero exit status
# the condition here being (($#)) which is arithmetic evaluation - the return
# status is 0 if the arithmetic value of the expression is non-zero; since $#
# holds the number of positional parameters then 'while (($#)); do' means run the
# commands as long as there are positional parameters (i.e. file names)

mv -- "${1}" "${1/DSC/Paris}"
# this renames the current file in the list

shift
# this actually takes a parameter - if it's missing it defaults to '1' so it's
# the same as writing 'shift 1' - it effectively removes $1 (the first positional
# argument) from the list so $2 becomes $1, $3 becomes $2 and so on...
done

1:它不是文本处理工具的替代品,所以绝不使用while循环来处理文本。

答案2

for-循环通常会重新完成静止的数据。也就是说,数据在循环过程中或在已知的时间间隔内不会改变。

while当不知道需要多少次迭代时,通常使用循环,例如提示用户输入并验证响应直到正确,或者循环从文件或管道读取的数据。

在这种情况下,您将循环直接从当前目录读取的文件名,由 shell 扩展文件通配模式赋予循环。循环for是正确使用的循环结构。循环while只会使事情变得复杂,并使代码更难以阅读和正确执行。

这是一个while与循环执行相同操作的循环示例for

printf '%s\n' DSC*.JPEG |
while read -r name; do
    [ ! -f "Paris${name#DSC}" ] && mv "$name" "Paris${name#DSC}"
done

这里有问题:

  1. 文件名不能包含换行符,因为循环读取换行符分隔的名称。我们可以通过获取printf输出\0分隔的文件名并read读取它们来解决这个问题,但这会使它变得更加复杂(并且不可移植)。
  2. 没有任何收获。名称列表仍然是静态的,我们引入了一个冗余步骤来将这些名称传递到printf循环,该步骤带来了我们可以允许文件名包含哪些字符的问题(请参阅上一点)。

实际上,您的代码唯一的问题是变量扩展未加引号。

答案3

until如果您愿意,还可以使用 Bash循环。

set -- *.jpeg
until ((! $#))
do
    mv -- "${1}" "${1/DSC/Paris}"
    shift
done

相关内容