@GeorgeVasiliou 已经展示了如何做你想做的事;我将尝试解释您的原始脚本有什么问题。在许多地方,您尝试执行的操作都使用了错误的语法。
for file in $ls
这将扩展名为ls 的shell 变量,将其内容拆分为单词,将在这些单词中找到的任何通配符扩展为匹配文件列表,然后遍历结果。但是没有定义 ls 变量,因此它扩展为空,并且循环永远不会运行。我认为您正在尝试迭代 ls 命令的输出;其语法为for file in $(ls)。但是你不应该这样做,因为文件名可以包含空格、制表符、换行符和通配符以及其他各种有趣的字符,这些字符可以使这个迭代......不是文件名列表。请参阅 BashFAQ 条目 'Why you shouldn't parse the output of ls(1)'。
您应该改用for file in *。 * 被扩展为匹配文件列表(当前目录中的所有可见文件),然后该列表不会以任何方式混淆,只是直接迭代。唯一的潜在问题是,如果没有任何匹配项,扩展将被跳过,循环运行一次,file 设置为“*”。
echo $file
当使用一个没有双引号的变量时,它将经历我上面描述的分词和通配符扩展过程。通常,什么都不会发生。有时,奇怪和意想不到的事情会发生。使用双引号,例如echo "$file"。
for f in $file
for ... in ... 语句迭代单词,而不是字符。 shell 没有特别好的方法来遍历字符串中的字符,但是您可以使用 for ((i=0; i<${#file}; i++)); do 遍历字符编号,然后使用 "${file:$i:1}" 获取单个字符。
哦,for (( )) 和 ${var:start:length} 构造是 bash 扩展,并非在所有 shell 中都可用。如果您想在脚本中使用其中一个或两个,请务必以特定于 bash 的 shebang 行(#!/bin/bash 或 #!/usr/bin/env bash)开始。
if [ $f -eq $dot ];
再次,双引号变量引用以避免在变量包含空格或通配符或为空白时造成混乱。此外,在[ ] 测试中,-eq 运算符进行数字比较而不是字符串比较;如果你给它的字符串不是有效的数字,它会给出一个错误。对于字符串比较,请改用=。此外,行尾不需要分号(好吧,除了case 的结尾等少数地方)。如果then 在同一行,则在此处使用分号,但如果在下一行,则不用。
count=$count+$f
这里的+ 将作为文字字符插入到变量值中。要附加两个变量,只需使用count="$count$f" 之类的东西。 (注意:这实际上是少数几个可以安全地去掉双引号的地方之一。但我还是建议使用它们,因为很难跟踪哪里是安全的,哪里不安全,所以更容易总是双引号你的变量。)
mv $file $count
再次,双引号。此外,当像这样运行任何类型的自动批量重命名/移动时,您应该始终使用 mv -n 或 mv -i 以防止在发生命名冲突(或错误或其他)时覆盖文件.
实际上,当我第一次运行这样的 mass-mv 脚本时,我喜欢在活动命令(例如 echo mv -n "$file" "$count")之前添加 echo,这样我就可以进行试运行并确保它是在我删除echo 并真正运行它之前,我会按照我的预期去做。