2015-06-20 130 views
1

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區塊意味着什麼?

有人可以幫忙解析一下嗎?這是迭代目錄中某種類型文件的正確方法嗎?

回答

1

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

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

1

一般情況下,你需要使用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. <<(...)之間的空間,以避免產生令牌<<,這會顯示一個這裏的文件。相反,它指定來自進程替換(<(...))的重定向(<)。