GNU find:在-exec中取得絕對和相對路徑

GNU find:在-exec中取得絕對和相對路徑

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也像finddoes 一樣包含隱藏文件。


作為旁注,在一般情況下:

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

如此$dphane,不$'\xa9phane'

但在特定情況下d=$a/$b,應該沒問題,因為系統區域設定中通常可用的字元集都不會包含/包含 編碼的字元以外的字元/

相關內容