Bash

發現目錄中的空間無法按預期工作

  • July 18, 2019

我有一個腳本呼叫這個

find "/mnt/Data/Shared/$1" -type d -exec bash -c 'fixperm "'${1}'" "fd" "$0"' {} \;

$1 是一個目錄,當名稱不包含空格時它可以工作,當有空格時它會失敗並返回錯誤。使用“00_Office 測試”進行測試

Test" "fd" "$0": -c: line 0: unexpected EOF while looking for matching `"'
Test" "fd" "$0": -c: line 1: syntax error: unexpected end of file

我認為這可能是因為路徑在空格之前缺少 \ 但這並不能解決問題。我確定我在這裡遺漏了一些微不足道的東西。

那是因為您使用的是未引用的${1}.

報價

解決報價問題可能會變得相當複雜。

替換'${1}''"${1}"'似乎有幫助。

比較:

$ set -- "ab cd"; bash -c 'printf "<%s> " '${1}' "fd" "$0"'
<ab>

和:

$ set -- "ab cd"; bash -c 'printf "<%s> " '"${1}"' "fd" "$0"'
<ab> <cd> <fd> <bash>

但是,shell“引號刪除”仍然應用於變數值。

作為一種解決方法,您可以使用'"${1@Q}"'

$ set -- 'a"b c"d'; bash -c 'printf "<%s> " '"${1}"' "fd" "$0"'; echo
<ab cd> <fd> <bash>               # quotes got lost.

$ set -- 'a"bc"d'; bash -c 'printf "<%s> " '"${1@Q}"' "fd" "$0"'; echo
<a"b c"d> <fd> <bash>             # correct quotes.

但是,這仍然不適用於您的命令具有的兩個 shell 暴露循環(首先是find命令,然後是bash -c命令):

$ mkdir 'a"bc"d' 'a"b c"d' 'a"bcd'

$ set -- 'a"bc"d'; find "./$1" -type d -exec bash -c 'printf "<%s> " fixperm "'"${1}"'" "fd" "$0"' {} >
<fixperm> <abcd> <fd> <./a"b c"d>

$ set -- 'a"b c"d'; find "./$1" -type d -exec bash -c 'printf "<%s> " fixperm "'"${1}"'" "fd" "$0"' {} >
<fixperm> <ab> <cd> <fd> <./a"b c"d>

$ set -- 'a"bcd'; find "./$1" -type d -exec bash -c 'printf "<%s> " fixperm "'"${1}"'" "fd" "$0"' {} \; 
./a"bcd: -c: line 0: unexpected EOF while looking for matching `"'
./a"bcd: -c: line 1: syntax error: unexpected end of file

正確的

$1但是,真正發生的是,您呼叫的腳本的參數與$1被呼叫的 shell 的含義之間似乎存在混淆bash -c

該行:

find "/mnt/Data/Shared/$1" -type d -exec bash -c '
    fixperm "'"${1}"'" "fd" "$0"' {} \;

應該讀:

find "/mnt/Data/Shared/$1" -type d -exec bash -c '
    fixperm "$1" "fd" "$2"' bash-shell "$1" {} \;

這使得報價直接且更加穩健。

簡單的

如果腳本中沒有循環或其他復雜的函式可以執行bash -c,幾乎所有的引用都可以去掉並寫成:

dir="/mnt/Data/Shared"

find "$dir/$1" -type d -exec fixperm "$1" fd {} \;

那是因為它${1}出現在單引號之外,即它find甚至在看到它之前就被shell 擴展和分詞。StackExchange 上突出顯示的語法清楚地表明了這一點。使用雙引號來防止分詞。

此外,通過呼叫bash -c,您需要自己處理引用,但如果文件名包含雙引號,它可能會中斷。不要使用它,直接傳遞參數:

find "/mnt/Data/Shared/$1" -type d -exec fixperm "$1" fd {} \;

引用自:https://unix.stackexchange.com/questions/530676