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,应该没问题,因为系统区域设置中通常可用的字符集都不会包含/包含 编码的字符以外的字符/

相关内容