计算文件名与字符串匹配的目录中的文件

时间:2016-04-29 08:11:59

标签: linux bash shell unix

命令:

ls /some/path/some/dir/ | grep some_mask_*.txt | wc -l
通过bash上的ssh执行此操作时,

返回正确数量的文件。当我把它放入.sh脚本

iFiles=`ls /some/path/some/dir/ | grep some_mask_*.txt | wc -l`
echo "iFiles: ${iFiles}"

总是0。这有什么不对吗?

解决方案:
当我研究它时,我发现我的“通配符掩码”似乎是问题所在。使用grep some_mask_ | grep \.txt而不是上面的单个grep帮我解决了第一个问题。

我将答案标记为解决方案,几乎完全描述了我犯了什么错误。我现在要编辑我的脚本。谢谢大家。

9 个答案:

答案 0 :(得分:6)

Parsing ls is not a good thing。如果您要查找文件,请使用find

find /some/path/some/dir/ -maxdepth 1 -name "some_mask_*.txt" -print0

这将打印与该目录中的条件匹配的文件,而不会进入子目录。当文件名不包含常见字符时,使用print0可防止出现奇怪的情况:

-print0
      True; print the full file name on the standard output,  followed
      by  a  null  character  (instead  of  the newline character that
      -print uses).  This allows file names that contain  newlines  or
      other  types  of white space to be correctly interpreted by pro‐
      grams that process the find output.  This option corresponds  to
      the -0 option of xargs.

然后,只需输入wc -l即可获得最终计数。

顺便说一句,请注意

ls /some/path/some/dir/ | grep some_mask_*.txt

可以简化为简单的

ls /some/path/some/dir/some_mask_*.txt

答案 1 :(得分:3)

我建议使用find,如下所示。原因是文件名可能包含会破坏正在使用wc -l的脚本的换行符。我只为每个文件名打印一个点,并用wc -c计算点数:

find /some/path/some/dir/ -maxdepth 1 -name 'some_mask_*.txt' -printf '.' | wc -c

或者如果您想将结果写入变量:

ifiles=$(find /some/path/some/dir/ -maxdepth 1 -name 'some_mask_*.txt' -printf '.' | wc -c)

答案 2 :(得分:2)

这里的问题是grep some_mask_*.txt是由shell而不是grep扩展的,所以很可能你在执行grep的目录中有一个匹配some_mask_*.txt的文件,然后使用该文件名通过grep作为过滤器。

如果要确保grep使用该模式,则需要将其用单引号括起来。此外,您需要将模式编写为正则表达式而不是通配符匹配(bash用于匹配)。将命令行版本放在一起应该是:

ls /some/path/some/dir/ | grep 'some_mask_.*\.txt' | wc -l

和脚本:

iFiles=`ls /some/path/some/dir/ | grep 'some_mask_.*\.txt' | wc -l`
echo "iFiles: ${iFiles}"

请注意,.需要以反斜杠作为前缀,因为它具有与单个字符匹配的正则表达式的特殊意义。

我还建议您使用$后缀regexp以便将其锚定到最后(从而确保正则表达式匹配以" .txt"结尾的文件名):

ls /some/path/some/dir/ | grep 'some_mask_.*\.txt$' | wc -l

答案 3 :(得分:1)

简单的解决方案是(对于bash)

find -name "*pattern*" | wc -l
  • “ *”代表任何内容(前缀-之前的任何内容,后缀-以后的任何内容)
  • wc -l:计数
  • find -name:将使用双引号查找具有给定名称的文件

答案 4 :(得分:0)

试试这个,

iFiles=$(ls /some/path/some/dir/ | grep some_mask_*.txt | wc -l)
echo "iFiles: ${iFiles}"

答案 5 :(得分:0)

我认为不会出现shell版本问题。

尝试在命令中使用escape char。它喜欢以下。

ls /some/path/some/dir/ | grep some_mask_\*.txt | wc -l

答案 6 :(得分:0)

您的问题是由于 shell扩展造成的。您可能在原始目录中测试了命令行,但是如果您从另一个目录中尝试它,那么它将不再起作用。

键入时:

grep *.txt

然后shell将*.txt替换为与模式对应的所有文件名,然后执行命令(类似grep a.txt dummy.txt)。但是您希望模式由grep解释,而不是由shell扩展,所以:

ls /tmp | grep '.*.cpp'
威尔做到了。这里的模式使用grep命令的语法(每个命令作为自己的语法)和未扩展,因为它受到环境'的保护。

修改您的命令,如:

a=`ls /tmp | grep '.*.cpp'`

答案 7 :(得分:0)

这与其他答案非常相似,但具有更强的稳健性

iFiles=$( find /some/path/ -name "some_mask_*.txt" -type f 2> /dev/null | wc -l )
echo "Number of files: $iFiles"

这会限制查找文件并将stderr管道为null,因此如果find命令不起作用或有权限问题,则不会出现虚假结果。

答案 8 :(得分:-2)

我正在编写一个Shell脚本来计算目录中相同格式的文件。为此,我使用了以下命令

LOCATION=/home/students/run_date/FILENAME #stored the location in a variable
DIRECTORYCOUNT=$(find $LOCATION -type d -print | wc -l) using find command 
DIRECTORYCOUNT=$(find $LOCATION -type f -print | wc -l) 

我已经使用了上面的命令并在此处输入了很好的代码