echo
我有一個我想運行的命令(不是!),它採用絕對路徑和相對路徑。
我如何得到這兩個參數?
試圖:
d=/tmp/foo;
find "$d" -type f -exec bash -c 'echo d=${1:${#d}} 1="${1%/*}"' bash {} \;
(我喜歡 GNU find,因為它是遞歸的,可以按檔案限制,可以按檔案名稱過濾,並且不會產生過多的 shell)
期待:
mkdir -p /tmp/foo/bar/can/haz; touch /tmp/foo/bar/can/haz/bzr.txt
# cmd is run, output is:
d=bar/can/haz 1=/tmp/foo/bar/can/haz
答案1
匯出d
,然後它將在您的內聯腳本中可用bash
。你也bash
根本不需要這裡。你的(希望更苗條/更快)sh
也會這樣做。此外,您不需要為每個檔案執行一個 shell。您可以使用以下變體將更多文件傳遞給內聯腳本-exec cmd {} +
:
d=/tmp/foo
export d
find "$d" -type f -exec sh -c '
for file do
relative=${file#"$d/"}
dir=${file%/*}
relative_dir=${relative%/*}
relative_dir=${relative_dir:-.}
printf "%10s: %s\n" full "$file" \
relative "$relative" \
dir "$dir" \
reldir "$relative_dir"
done' sh {} +
這使:
full: /tmp/foo/bar/can/haz/bzr.txt
relative: bar/can/haz/bzr.txt
dir: /tmp/foo/bar/can/haz
reldir: bar/can/haz
但如果您只需要相對路徑,那麼執行以下操作可能會更簡單:
(cd -P -- "$d" && find . -exec sh -c 'for file do...' sh {} +)
這也將使傳遞的命令參數sh
更短,因此允許find
傳遞更多參數sh
。
請注意,你的命令和我的命令中都沒有任何特定於 GNU 的內容find
。這應該適用於任何符合 POSIX 標準的find
實現,而不僅僅是 GNU 實作。您問題中唯一的非 POSIX 部分顯然是Korn shell 運算符,而不是 POSIX 中的運算bash
符。${1:offset}
sh
對於允許您指定文件類型的遞歸文件查找,另請參閱zsh
:
(cd -P -- "$d" &&
for file (**/*(ND.)) {
dir=$file:h
printf '%10s: %s\n' relative $file reldir $dir
})
上面,.
相當於find
's -type f
(僅限常規文件),而D
也像find
does 一樣包含隱藏文件。
作為旁注,在一般情況下:
c=$a$b; d=${c:${#a}}
[ "$b" = "$d" ] && echo yes
不保證輸出“yes”,因為${#var}
and${var:offset}
運算子與人物, 不是位元組。
a
例如,在 UTF-8 語言環境中,對於和 的這些值,它不會輸出 yes b
:
a=$'St\xc3' b=$'\xa9phane'
有了這些,$c
將包含我的名字 ( Stéphane
)包含該字符$a
的一半,另一半將是(2 個字符和 1 個位元組不形成有效字符,但仍然計數)。é
$b
${#a}
3
如此$d
會phane
,不$'\xa9phane'
。
但在特定情況下d=$a/$b
,應該沒問題,因為系統區域設定中通常可用的字元集都不會包含/
包含 編碼的字元以外的字元/
。