如何让 shell 识别 `ls -A` 命令返回的文件名,并且这些名称包含空格?

如何让 shell 识别 `ls -A` 命令返回的文件名,并且这些名称包含空格?

这是我用来重命名返回的文件的脚本的一部分ls -A

for FILE in `ls -A`
do
        ext=${FILE##*.}
        NUM=$(($NUM+1))
        NEWFILE=`echo $2_$NUM.$ext | sed 's/ /_/g'`

        mv "$FILE" "$NEWFILE"
done

但找不到带空格的名称!$2 参数不可能是导致错误的原因,为什么我曾经将不带空格的名称作为参数,并且此脚本会使用该名称并重命名文件夹中的所有文件,以便让它们编号并且不会修改文件扩展名。不幸的是,它不会重命名名称中带有空格的文件。有人能帮我吗?

答案1

for迭代,单词由空格分隔。您不应该迭代 的输出ls,而应该使用* .*

for file in * .* ; do
    if [[ $file = . || $file = .. ]] ; then
        continue
    fi
    # ...
done

答案2

您可以通过设置dotglob shell 选项

shopt -s dotglob
for file in *
do 
  echo "$file"
done

例如,对于包含 和 (最后一个是隐藏的并且有一个空格)的目录file,这将file with spaces产生.hidden file

file
file with spaces
.hidden file

您可能还想添加nullglob选项,以防止在目录为空的情况下出现错误情况 - 请参阅优秀的Bash常见问题/004。记得给变量加上引号"$file",并且最好不要使用全大写的变量名。

答案3

ls -A对我来说,在一行中写入多个文件名,以空格分隔。如果您尝试添加,则-1ls -A1行将输出一个文件名,这可能对您来说效果更好。

我遇到了与文件名中的空格相同的问题,尤其是在使用 find 时,但用空字符分隔名称可以处理文件名中的空格和换行符:
find (...) -print0 | xargs -0 (do stuff here)

但是,如果您只是想重命名文件,您可能会考虑man rename它可以执行如下操作:

For example, to rename all files matching "*.bak" to strip the extension,
you might say
     rename 's/\.bak$//' *.bak
To translate uppercase names to lower, you'd use
     rename 'y/A-Z/a-z/' *

或者对于一些目录的 GUI 解决方案,Thunar 有一个很好的“重命名多个文件”界面,可以按照您描述的方式进行编号。我刚刚尝试将一些带空格的文件名与 find 结合到 Thunar,它似乎有效:
find . -type f -print0 | xargs -0 thunar -B

答案4

怎么样:

ls -A | while read fname
do
    echo "$fname" # your code goes here
done

管道ls强制它每行发送 1 个文件名,read然后将该行接受到变量中fname

相关内容