腳本錯誤。命令 find 正在跳過帶有空格字元的資料夾

腳本錯誤。命令 find 正在跳過帶有空格字元的資料夾

我需要一個計算目錄(和子目錄)中檔案數量的腳本。我採用了以下腳本,並將其更改為我的需要。

除了帶有空格字元的資料夾之外,它的工作方式與應有的方式相同。我很確定我在任何地方都缺少引號,但還無法弄清楚。

附加資訊

  • Linux 2.6.22.19-0.4-default(此伺服器不再處於生產環境。)
  • GNU 查找版本 4.2.31
  • 我無法重命名目錄。

目錄結構範例

.
..
01_infos
02_sent
03_inbox
04_public and private
197.
145.
329.
13.

腳本

#!/bin/bash
# Write a script that will count the number of files in each of your subdirectories.
# -------------------------------------------------------------------------
# Copyright (c) 2001 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------

START=$HOME

# change your directory to command line if passed
# otherwise use home directory
[ $# -eq 1 ] && START=$1 || :

if [ ! -d $START ]
then
        echo "$START not a directory!"
        exit 1
fi

# use find command to get all subdirs name in DIRS variable
DIRS=$(find "$START" -type d)

# loop thought each dir to get the number of files in each of subdir
for d in $DIRS
do
        echo "$d directory has $(find "$d" -maxdepth 1 -regex '.*\.' -type f | wc -l) files" || :
done

輸出

./01_infos directory has 1 files
./02_sent directory has 9 files
./03_inbox has 4 files
find: ./04_public: No such file or directory

答案1

你缺少一些雙引號(總是在變數替換兩邊加上雙引號$foo始終在變數替換和命令替換$(foo),除非您知道為什麼可以安全地離開它們並且需要離開它們)。但這還不是問題的全部。

if [ ! -d $START ]

應該if [ ! -d "$START" ]

DIRS=$(find "$START" -type d)

此時,DIRS遞歸包含起始目錄及其子目錄的名稱,中間有換行符。因此,如果您有任何包含換行符的目錄名,那麼您就迷失了:不可能知道哪些換行符號來自目錄名以及哪些是分隔符號。如果您知道檔案名稱中沒有換行符,則可以解析以下輸出find,但您怎麼知道呢?

順便說一句,這裡沒有雙引號是可以的,$(…)因為這是一個變數賦值,而賦值中的替換是隱式保護的。但請注意,它export DIRS=$(…)沒有受到類似的保護。最好使用引號,除非您精通 shell 腳本編寫,並且所有維護您的腳本的人也是如此。

for d in $DIRS

這就是你失敗的地方:你想分成$DIRS單詞,所以你不能加雙引號,但你需要雙引號,因為$DIRS所有元素都連接在一起,並且如果你不加引號,空格內的文件名將成為分隔符。


通常,當您使用 時find,您應該讓它呼叫處理命令,並帶有-exec選項。除非您對檔案名稱有嚴格的控制,否則不要解析 的輸出find:它是不明確的。

find "$START" -type d -exec sh -c '
    echo "$0 directory has $(find "$0" -maxdepth 1 -regex ".*\\." -type f -printf \\n | wc -l) files whose name ends with ."
' {} \;

再次注意,在嵌入find命令中,如果解析 的輸出find,如果任何檔案名稱包含換行符,則計數將關閉。

答案2

就這個怎麼樣?

find . -type d -exec sh -c '/bin/echo -n "{}"; find "{}" -maxdepth 1 -regex ".*\." -type f | wc -l; ' \;

輸出並不那麼甜蜜,但它不需要腳本,並且適用於帶有空格以及其他非字母數字字元的目錄。

答案3

你有一個經典的引用錯誤。將 for 迴圈修復為如下所示:

for d in "$DIRS"

或者,您可以find直接輸入它的輸出,例如:

find "$START" -type d | while read d
do # and so on...

順便說一句,該|| :位是完全多餘的,因為echo傳回值始終為 0。

相關內容