如何將查找結果儲存在變數中,以便在修改它們之前可以顯示它們?

如何將查找結果儲存在變數中,以便在修改它們之前可以顯示它們?

我有這個腳本可以查找權限不正確的檔案。如果發現任何問題,它會詢問使用者是否要修復它們或顯示它們。查找結果儲存在變數中以避免多次運行相同的命令:

#!/usr/bin/env sh

results=$(find "$0" -type f -not -perm 644)

if [ -z "$results" ]; then
    echo 'No files with incorrect permissions found'
else
    while true; do
        read -p 'Fix files with incorrect permissions? (yes/no/show) ' ans
        case "$ans" in
            Y | y | yes)
                echo 'Changing file permissions...'
                chmod 644 "$results"
                break;;
            N | n | no)
                break;;
            S | s | show)
                echo "$results";;
            *)
                echo 'Please answer yes or no';;
        esac
    done
fi

問題是chmod由於換行符號而引發錯誤:

chmod: cannot access 'test/foo'$'\n''test/bar'$'\n''test/foo bar': No such file or directory

如果我刪除周圍的引號"$results",效果會好一點,但當然包含空格的檔名會出現問題。

我一直在搞亂,IFS=$'\n'但不知道應該在哪裡設置。這似乎不起作用:

IFS=$'\n' chmod 644 $results

然而,這確實:

IFS=$'\n'
chmod 644 $results
unset IFS

我想我只是想知道這是否正確或是否有更好的方法。

答案1

設定IFS為僅換行符會有所幫助,但它仍然會留下以下問題:1)帶有換行符的檔案名稱(顯然),以及2)帶有全域字元的檔案名稱。例如,名為的檔案*將擴展到目錄中的所有檔案名稱。

在 Bash 中,使用mapfile/readarray來填入陣列:

mapfile -d '' files < <(find . -type f ! -perm 0644 -print0)
printf "%d matching files found\n" "${#files[@]}"
printf "they are:\n"
printf "  %q\n" "${files[@]}"

也可以看看:

答案2

IFS如果我在之前chmod/之後設定/取消設定它,它看起來效果一樣好,而不是之前設定並在之後立即取消設定find 按照註解中的建議將子 shell 包裝在陣列中:

IFS=$'\n'
results=($(find "$0" -type f -not -perm 644))
unset IFS

這樣,chmod 644 "${results[@]}"只要沒有包含換行符的檔案名,數組就有正確的項目數量,並且可以按預期工作(儘管我無法想像為什麼有人會故意這樣做)。

相關內容