以下代码可以在当前文件夹中正常工作,但我希望它也可以扫描子文件夹。
for file in *.mp3
do
echo $file
done
for file in $(find . -name '*.mp3') do
echo $file
TITLE=$(id3info "$file" | grep '^=== TIT2' | sed -e 's/.*: //g')
ARTIST=$(id3info "$file" | grep '^=== TPE1' | sed -e 's/.*: //g')
echo "$ARTIST - $TITLE"
done
find . -name '*.mp3' -print0 | while read -d $'\0' file
do
echo $file
TITLE=$(id3info "$file" | grep '^=== TIT2' | sed -e 's/.*: //g')
ARTIST=$(id3info "$file" | grep '^=== TPE1' | sed -e 's/.*: //g')
echo "$ARTIST - $TITLE"
done
另外一种方法是保存和恢复 IFS
。感谢David W.的评论,特别是指出while
循环版本也具有一个好处,即它将正确处理非常大量的文件,而第一个版本将使用$(find)
展开成for循环,会在某个时刻无法工作,因为shell扩展有限制。
IFS
或使用-print0
来解决这个问题。我会编辑一个解决方案进去。 - drquicksilver子句并将其替换为我的
for`。我的命令行缓冲区不可能那么大,结果就是我的查找将会简单失败。在使用shell扩展到for循环时,您应该非常小心。 - David W.太多的答案使用shell扩展来存储find命令的结果。这不是你轻易应该做的事情。
假设我有30,000首歌曲,这些歌曲的标题平均约为30个字符。现在先不要考虑空格的问题。
我的find命令将返回超过1,000,000个字符,很可能我的命令行缓冲区不够大。如果我做了这样的事情:
for file in $(find -name "*.mp3")
do
echo "some sort of processing"
done
find
中的溢出内容。甚至可能完全静默地失败。xargs
命令被创建的原因。它确保命令行缓冲区永远不会溢出。它将执行跟随xargs
的命令,直到保护命令行缓冲区的次数足够多:$ find . -name "*.mp3" | xargs ...
xargs
和 find
实现了一种处理此问题的方法:$ find . -name "*.mp3 -print0 | xargs --null ...
如果你能保证文件名中不会含有制表符、\n
(或双空格),那么将查找命令的输出传递给 while 循环更为优秀:
find . -name "*.mp3" | while read file
do
while read
。更好的是,read file
会读取整行,并将该行中找到的所有项目放入$file
中。它并不完美,因为read
仍然会在空格处断开,所以文件名如下:I will be in \n your heart in two lines.mp3
I love song names with multiple spaces.mp3
I \t have \t a \t thing \t for \t tabs.mp3.
仍然会失败。变量$file
将把它们视为:
I will be in
your heart in two lines.mp3
I love song names with multiple spaces.mp3
I have a thing for tabs.mp3.
find ... -print0
将null作为输入分隔符。然后要么更改IFS
以使用null,要么在BASH shell的while read语句中使用-d\0
参数。ls
的代码片段,应该有一个巨大的红色“在继续之前请阅读此内容”标志。看起来这种问题的数量是如此之大,以至于它实际上会节省提问者和这里的乐于助人的人们很多时间。鉴于这种问题的错误答案数量,哦,天哪... - Adrian Frühwirth这适用于大多数文件名(包括空格),但不能处理换行符、制表符或双空格。
find . -type f -name '*.mp3' | while read i; do
echo "$i"
done
这适用于所有文件名。
find . -type f -name '*.mp3' -print0 | while IFS= read -r -d '' i; do
echo "$i"
done
但如果你只想运行一个命令,可以使用 xargs
命令,例如:
find . -type f -name '*.mp3' -print0 | xargs -0 -l echo
find . -name *.mp3 -exec echo {} \;
字符串{}
在命令参数中的所有出现位置都将被当前正在处理的文件名替换,而不仅仅是在独立的参数中,这与某些版本的find命令不同。请查看find man手册以获取更多信息:http://unixhelp.ed.ac.uk/CGI/man-cgi?find
看起来你正在寻找find命令。我还没有测试过,但大致是这样的:
files=(`find . -name *.mp3`)
for file in "${files[@]}"; do
echo $file TITLE="id3info "$file" | grep '^=== TIT2' | sed -e 's/.*: //g'" ARTIST="id3info "$file" | grep '^=== TPE1' | sed -e 's/.*: //g'"
done
编辑:使用数组可以使命令对于文件名中包含空格的文件更加安全。
find . -name \*.mp3 -exec yada yada yada
- Marc B