使用Bash遍历目录中的特定文件find

问题描述:

Shellcheckdoesn't like my for over find在Bash中循环。使用Bash遍历目录中的特定文件find

for f in $(find $src -maxdepth 1 -name '*.md'); do wc -w < "$f" >> $path/tmp.txt; done

这表明代替:

1 while IFS= read -r -d '' file 
2 do 
3  let count++ 
4  echo "Playing file no. $count" 
5  play "$file" 
6 done < <(find mydir -mtime -7 -name '*.mp3' -print0) 
7 echo "Played $count files" 

我了解大部分,但有些事情还不清楚。

第一行:什么是'' file

第6行:空白空间在< < (find).中做什么<像往常一样重定向?如果是,那么重定向到do区块意味着什么?

有人可以帮忙解析一下吗?这是迭代目录中某种类型文件的正确方法吗?

第一行:什么是''文件?

help read,即''是一个参数传递给-d参数:

-d delim continue until the first character of 
      DELIM is read, rather than newline 

在线路六:什么空白处做< <(查找)。

这里有两个独立的操作符。有<,标准I/O重定向操作,随后是<(...)构建体,其是特定的bash构建体,其执行过程取代:

Process Substitution 

    Process substitution is supported on systems that 
    support named pipes (FIFOs) or the /dev/fd method of naming 
    open files. It takes the form of <(list) or >(list). The 
    process list is run with its input or output connected 
    to a FIFO or some file in /dev/fd... 

因此,这是正在发送find命令的输出入do 循环。

<是否像往常一样重定向?如果他们是,那么重定向到阻止什么意思?

重定向进入一个循环意味着环路 从stdin读取内部的任何命令将从重定向的输入源中读取。作为 的副作用,该循环内的所有内容都在一个子shell中运行,该子shell对变量范围有 的影响:在循环外部, 循环内设置的变量不可见。

有人可以帮忙解析一下吗?这是迭代目录中某种类型文件的正确方法吗?

为了记录在案,我通常会通过管道向findxargs, 虽然它的解决方案是最好的做这取决于在一定上你想做什么 延伸。在你的问题中的两个例子完全不同的事情,并不清楚你实际上试图完成 。

但例如:

find $src -maxdepth 1 -name '*.md' -print0 | 
    xargs -0 -iDOC wc -w DOC 

这将在所有*.md文件运行wc-print0find (和-0xargs)允许该命令正确处理具有嵌入空白的 文件名(例如,This is my file.md)。如果 你知道你没有任何这些,你只是做:

find $src -maxdepth 1 -name '*.md' | 
    xargs -iDOC wc -w DOC 
+0

计数的话在所有降价文件,在第一个例子。第二个例子来自这个建议。谢谢你的回答! – denten

一般情况下,你需要使用find如果你想通过做一个目录树进行递归搜索(虽然有现代化的bash,你可以设置shell选项globstar,如shellcheck建议的那样)。但在这种情况下,你已经-maxdepth 1指定的,所以你的find命令刚刚上市的匹配模式"$src"/*.md哪些文件。既然如此,这是更简单,使用更可靠的水珠(模式):

for f in "$src"/*.md; do 
    wc -w < "$f" 
done >> "$path"/tmp.txt 

(我还引用了所有的变量扩展,安全和移动的输出重定向所以它适用于整个)

如果您需要使用find(因为glob不起作用),那么您应该尝试使用-exec选项来查找,这并不需要绕过其他选项以避免在文件名中处理错误的特殊字符。例如,你可以这样做:

find "$src" -maxdepth 1 -name '*.md' -exec do wc -w {} + >> "$path"/tmp.txt 

为了回答您的具体问题:

  1. IFS= read -r -d '' file,该''是参数的-d选项。该选项用于指定划定要读取行的字符;默认情况下使用换行符,以便read一次读取一行。空字符串与指定NUL字符相同,如果您指定-print0选项,则find在每个文件名的末尾输出该字符。 (不像-exec-print0不是POSIX标准,因此不能保证每find实施工作,但实际上它是相当普遍可用。)

  2. <<(...)之间的空间,以避免产生令牌<<,这会显示一个这里的文件。相反,它指定来自进程替换(<(...))的重定向(<)。