Bash

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

  • November 23, 2017

我有一個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

Export 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.

請注意,您的find命令和我的命令中都沒有特定於 GNU 的內容。這應該適用於任何符合 POSIX 的find實現,而不僅僅是 GNU。您的問題中唯一的非 POSIX 部分顯然是 Korn shell 運算符,而不是bashPOSIX 。${1:offset}``sh

對於允許您指定文件類型的遞歸文件查找,另請參見zsh

(cd -P -- "$d" &&
 for file (**/*(ND.)) {
   dir=$file:h
   printf '%10s: %s\n' relative $file reldir $dir
 })

上面,.is 相當於find’s -type f(僅正常文件),而Dis 也包括隱藏的文件find


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

c=$a$b; d=${c:${#a}}
[ "$b" = "$d" ] && echo yes

不保證輸出“是”,因為${#var}and${var:offset}運算符使用字元,而不是字節

例如,在 UTF-8 語言環境中,它不會輸出帶有這些值的 yesab

a=$'St\xc3' b=$'\xa9phane'

有了這些,$c將包含我的名字 ( Stéphane)$a包含該é字元$b的一半,另一半${#a}將是3(2 個字元和 1 個字節不構成有效字元,但仍被計算在內)。

$d會的,phane不會$'\xa9phane'的。

但在特定情況下d=$a/$b,應該沒問題,因為系統語言環境中通常可用的字元集都不會包含除/包含/.

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