如何迭代 ls 返回的文件

如何迭代 ls 返回的文件

第一次和第二次调用是为了进行比较。这是我第三次尝试去上班。

$ ls -a1 *mp3
DaftPunk_VeridisQuo.mp3
French79_AfterParty.mp3
French79_BetweentheButtons.mp3
French79_Hometown.mp3
$ find . -maxdepth 1 -type f -name '*mp3'
./French79_AfterParty.mp3
./French79_Hometown.mp3
./DaftPunk_VeridisQuo.mp3
./French79_BetweentheButtons.mp3
$ for x in "$(ls -a *mp3)"; do mv "./$x" "./electro_$x"; done
mv: cannot stat './DaftPunk_VeridisQuo.mp3'$'\n''French79_AfterParty.mp3'$'\n''French79_BetweentheButtons.mp3'$'\n''French79_Hometown.mp3': No such file or directory

答案1

我更喜欢直接使用它:

for x in *.mp3
do 
    mv ./"$x"  "electro_$x"
done

答案2

通过引用$(..),您将得到一个标记,而不是 N 个标记:

我从几个示例文件开始:

$ ls
a.mp3 b.mp3 c.mp3

如果我按照你的做法,我会得到这三行的一行:

for i in "$(ls *.mp3)"; do
    echo "--> $i"
done
--> a.mp3 b.mp3 c.mp3

如果我省略 周围的引号$(...),我会得到三个不同的输出行:

for i in $(ls *.mp3); do
    echo "--> $i"
done
--> a.mp3
--> b.mp3
--> c.mp3

如果您的文件带有空格,那么类似这样的事情可能会解决您的问题(请注意,这仅适用于当前目录中的文件):

$ ls
'DaftPunk VeridisQuo.mp3'  'French79 AfterParty.mp3'  'French79 BetweentheButtons.mp3'  'French79 Hometown.mp3'

用于find重命名:

$ find *.mp3 -maxdepth 1 -type f -name *.mp3 -exec mv {} "electro_{}" \;
$ ls
'electro_DaftPunk VeridisQuo.mp3'  'electro_French79 AfterParty.mp3'  'electro_French79 BetweentheButtons.mp3'  'electro_French79 Hometown.mp3'

为什么我建议find *.mp3而不是简单地建议find . -type f -name '*.mp3' ...

$ find . -maxdepth 1 -type f -name '*.mp3' -exec mv {} "electro_{}" \;
mv: cannot move './French79 Hometown.mp3' to 'electro_./French79 Hometown.mp3': No such file or directory
mv: cannot move './French79 BetweentheButtons.mp3' to 'electro_./French79 BetweentheButtons.mp3': No such file or directory
mv: cannot move './French79 AfterParty.mp3' to 'electro_./French79 AfterParty.mp3': No such file or directory
mv: cannot move './DaftPunk VeridisQuo.mp3' to 'electro_./DaftPunk VeridisQuo.mp3': No such file or directory

答案3

您想要做的是一个简单的批量重命名,可以通过 perlrename实用程序(又名prenamefile-rename)轻松处理。这是不是rename与包中的实用程序相同util-linux(具有完全不同且不兼容的命令行选项和功能)。

尝试

rename -n 's/^/electro_/' *.mp3

-n选项使其成为一次试运行,只会展示如果您允许,您将如何重命名 .mp3 文件。要实际重命名它们,请删除-n或将其替换-v为详细输出。

$ touch DaftPunk_VeridisQuo.mp3 French79_AfterParty.mp3 French79_BetweentheButtons.mp3

$ ls -l
total 2
-rw-r--r-- 1 cas cas 0 Oct 21 14:30 DaftPunk_VeridisQuo.mp3
-rw-r--r-- 1 cas cas 0 Oct 21 14:30 French79_AfterParty.mp3
-rw-r--r-- 1 cas cas 0 Oct 21 14:30 French79_BetweentheButtons.mp3

$ rename -v 's/^/electro_/' *.mp3
DaftPunk_VeridisQuo.mp3 renamed as electro_DaftPunk_VeridisQuo.mp3
French79_AfterParty.mp3 renamed as electro_French79_AfterParty.mp3
French79_BetweentheButtons.mp3 renamed as electro_French79_BetweentheButtons.mp3

$ ls -l
total 2
-rw-r--r-- 1 cas cas 0 Oct 21 14:30 electro_DaftPunk_VeridisQuo.mp3
-rw-r--r-- 1 cas cas 0 Oct 21 14:30 electro_French79_AfterParty.mp3
-rw-r--r-- 1 cas cas 0 Oct 21 14:30 electro_French79_BetweentheButtons.mp3

答案4

使用IFS设置分隔符。通过换行符,空格不再是问题。

IFS=$(echo -en "\n\b")
for x in $(ls -1 *.mp3); do mv "$x" "electro_${x}"; done

当然,你可能会问为什么不简单地

IFS='\n'

这是因为$()或 反引号是命令替换,它会删除尾随的换行符。

来自BASH 手册

\n 换行符

\b 退格键

我的理解是,“返回”(向左移动)是为了防止删除尾随的换行符,从而允许它在for(每个)循环中进行迭代。

这在中进行了更详细的讨论一些 其他 堆栈溢出 问题

相关内容