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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36933032/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 14:34:49  来源:igfitidea点击:

Count files in a directory with filename matching a string

linuxbashshellunix

提问by Yaerox

The command:

命令:

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

returns the correct number of files when doing this via ssh on bash. When I put this into a .sh Script

在 bash 上通过 ssh 执行此操作时返回正确数量的文件。当我将其放入 .sh 脚本时

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

it is always 0. Whats wrong here?

它总是0。这里有什么问题吗?

Solution:
When I worked on it I found out that my "wildcard-mask" seems to be the problem. using grep some_mask_ | grep \.txtinstead of the single grep above helped me to solve the problem for the first.

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

I marked the answer as solution which pretty much describes exactly what I made wrong. I'm going to edit my script now. Thanks everyone.

我将答案标记为解决方案,它几乎准确地描述了我做错了什么。我现在要编辑我的脚本。谢谢大家。

回答by fedorqui 'SO stop harming'

Parsing ls is not a good thing. If you want to findfiles, use find:

解析 ls 不是一件好事。如果要查找文件,请使用find

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

This will print those files matching the condition within that directory and without going into subdirectories. Using print0prevents weird situations when the file name contains not common characters:

这将打印与该目录中条件匹配的那些文件,而无需进入子目录。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.

Then, just pipe to wc -lto get the final count.

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



By the way, note that

顺便说一下,请注意

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

can be reduced to a simple

可以简化为一个简单的

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

回答by hek2mgl

I suggest to use findas shown below. The reason for that is that filenames may contain newlines which would break a script that is using wc -l. I'm printing just a dot per filename and count the dots with wc -c:

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

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

or if you want to write the results to variable:

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

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

回答by Stefan Farestam

The problem here is that grep some_mask_*.txtis expanded by the shell and not by grep, so most likely you have a file in the directory where grep is executed which matches some_mask_*.txtand that filename is then used by grep as a filter.

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

If you want to ensure that the pattern is used by grep then you need to enclose it in single quotes. In addition you need to write the pattern as a regexp and not as a wildcard match (which bash uses for matching). Putting this together your command line version should be:

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

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

and the script:

和脚本:

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

Note that .needs to be prefixed with a backslash since it has special significance as a regexp that matches a single character.

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

I would also suggest that you postfix the regexp with $ in order to anchor it to the end (thus ensuring that the regexp matches filenames that ends with ".txt"):

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

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

回答by Rishabh Agarwal

Simple solution is (for bash)

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

find -name "*pattern*" | wc -l
  • "*" represent anything (prefix- anything before , postfix - anything after)
  • wc -l : give the count
  • find -name : will find file with given name in double quotes
  • “*”代表任何东西(前缀 - 之前的任何东西,后缀 - 之后的任何东西)
  • wc -l : 给出计数
  • find -name : 将在双引号中查找给定名称的文件

回答by mf_starboi_8041

Try this,

尝试这个,

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

回答by Dorleeze

I think there wouldn't be the shell version problem.

我认为不会有shell版本问题。

try to use escape char on your command. It likes below.

尝试在您的命令中使用转义字符。喜欢下面。

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

回答by Jean-Baptiste Yunès

Your problem is due to shell expansion. You probably tested the command line in the original directory, but if you try it from another directory then it will not work anymore.

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

When you type:

当你输入:

grep *.txt

then the shell replace *.txtwith all the file names that correspond to the pattern and then execute the command (something like grep a.txt dummy.txt). But you want the pattern to be interpreted by grepnot expanded by the shell, so:

然后外壳用*.txt与模式对应的所有文件名替换,然后执行命令(类似于grep a.txt dummy.txt)。但是您希望模式grep不被 shell 扩展解释,因此:

ls /tmp | grep '.*.cpp'

wille make it. Here the pattern is in the syntax of grepcommand (each command as its own syntax) and not expandedbecause it is protected with surroundings '.

会成功的。这里的模式是grep命令的语法(每个命令都是它自己的语法)并且没有扩展,因为它受到了环境的保护'

Modify your command like:

修改你的命令,如:

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

回答by Martin

This is quite similar to other answers, but with a bit more robustness

这与其他答案非常相似,但更具鲁棒性

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

This limits the find to files and also pipes stderr to null, so if the find command doesn't work or has permission issues you don't get a bogus result.

这将查找限制为文件并将 stderr 传递给 null,因此如果 find 命令不起作用或存在权限问题,您不会得到虚假结果。

回答by SAI CHAND GOUD PUJARI

I was writing a shell script to count the files of same format in a directory. For that I have used the below command

我正在编写一个 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) 

I have used above commands and enter code here it worked well

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