如何使用for-each循环在bash中迭代文件路径?

时间:2021-09-27 14:28:09

The following command attempts to enumerate all *.txt files in the current directory and process them one by one:

下面的命令尝试枚举所有*。当前目录下的txt文件,逐一处理:

for line in "find . -iname '*.txt'"; do 
     echo $line
     ls -l $line; 
done

Why do I get the following error?:

为什么会出现以下错误:

ls: invalid option -- 'e'
Try `ls --help' for more information.

4 个解决方案

#1


99  

Here is a better way to loop over files as it handles spaces and newlines in file names:

在处理文件名中的空格和换行符时,这里有一个更好的循环文件的方法:

find . -type f -iname "*.txt" -print0 | while IFS= read -r -d $'\0' line; do
    echo "$line"
    ls -l "$line"    
done

#2


19  

The for-loop will iterate over each (space separated) entry on the provided string.

for循环将在提供的字符串上迭代每个(分隔的)条目。

You do not actually execute the find command, but provide it is as string (which gets iterated by the for-loop). Instead of the double quotes use either backticks or $():

实际上,您并不执行find命令,但提供它为string(由for循环迭代)。而不是双引号使用backticks或$():

for line in $(find . -iname '*.txt'); do 
     echo "$line"
     ls -l "$line"
done

Furthermore, if your file paths/names contains spaces this method fails (since the for-loop iterates over space separated entries). Instead it is better to use the method described in dogbanes answer.

此外,如果您的文件路径/名称包含空格,则此方法失败(因为for循环遍历空格分隔的条目)。相反,最好使用dogbanes答案中描述的方法。


To clarify your error:

澄清你的错误:

As said, for line in "find . -iname '*.txt'"; iterates over all space separated entries, which are:

如前所述,在“查找”中。- iname * . txt”;遍历所有空间分隔的条目,它们是:

  • find
  • 找到
  • .
  • -iname
  • - iname
  • '*.txt' (I think...)
  • ' *。txt”(我认为…)

The first two do not result in an error (besides the undesired behavior), but the third is problematic as it executes:

前两个不会导致错误(除了不希望的行为),但是第三个会在执行时出现问题:

ls -l -iname

A lot of (bash) commands can combine single character options, so -iname is the same as -i -n -a -m -e. And voila: your invalid option -- 'e' error!

许多(bash)命令可以组合单个字符选项,因此-iname与i -n -a -m -e相同。瞧,你的无效选项——e错误!

#3


17  

More compact version working with spaces and newlines in the file name:

更紧凑的版本,使用文件名中的空格和换行:

find . -iname '*.txt' -exec sh -c 'echo "{}" ; ls -l "{}"' \;

#4


6  

Use command substitution instead of quotes to execute find instead of passing the command as a string:

使用命令替代代替引用来执行查找,而不是将命令作为字符串传递:

for line in $(find . -iname '*.txt'); do 
     echo $line
     ls -l $line; 
done

#1


99  

Here is a better way to loop over files as it handles spaces and newlines in file names:

在处理文件名中的空格和换行符时,这里有一个更好的循环文件的方法:

find . -type f -iname "*.txt" -print0 | while IFS= read -r -d $'\0' line; do
    echo "$line"
    ls -l "$line"    
done

#2


19  

The for-loop will iterate over each (space separated) entry on the provided string.

for循环将在提供的字符串上迭代每个(分隔的)条目。

You do not actually execute the find command, but provide it is as string (which gets iterated by the for-loop). Instead of the double quotes use either backticks or $():

实际上,您并不执行find命令,但提供它为string(由for循环迭代)。而不是双引号使用backticks或$():

for line in $(find . -iname '*.txt'); do 
     echo "$line"
     ls -l "$line"
done

Furthermore, if your file paths/names contains spaces this method fails (since the for-loop iterates over space separated entries). Instead it is better to use the method described in dogbanes answer.

此外,如果您的文件路径/名称包含空格,则此方法失败(因为for循环遍历空格分隔的条目)。相反,最好使用dogbanes答案中描述的方法。


To clarify your error:

澄清你的错误:

As said, for line in "find . -iname '*.txt'"; iterates over all space separated entries, which are:

如前所述,在“查找”中。- iname * . txt”;遍历所有空间分隔的条目,它们是:

  • find
  • 找到
  • .
  • -iname
  • - iname
  • '*.txt' (I think...)
  • ' *。txt”(我认为…)

The first two do not result in an error (besides the undesired behavior), but the third is problematic as it executes:

前两个不会导致错误(除了不希望的行为),但是第三个会在执行时出现问题:

ls -l -iname

A lot of (bash) commands can combine single character options, so -iname is the same as -i -n -a -m -e. And voila: your invalid option -- 'e' error!

许多(bash)命令可以组合单个字符选项,因此-iname与i -n -a -m -e相同。瞧,你的无效选项——e错误!

#3


17  

More compact version working with spaces and newlines in the file name:

更紧凑的版本,使用文件名中的空格和换行:

find . -iname '*.txt' -exec sh -c 'echo "{}" ; ls -l "{}"' \;

#4


6  

Use command substitution instead of quotes to execute find instead of passing the command as a string:

使用命令替代代替引用来执行查找,而不是将命令作为字符串传递:

for line in $(find . -iname '*.txt'); do 
     echo $line
     ls -l $line; 
done