GNU find: -exec で絶対パスと相対パスを取得する

GNU find: -exec で絶対パスと相対パスを取得する

echo絶対パスと相対パスを取るコマンド (ではありません!) を実行したいと考えています。

これら 2 つの引数を取得するにはどうすればよいですか?

試み:

d=/tmp/foo;
find "$d" -type f -exec bash -c 'echo d=${1:${#d}} 1="${1%/*}"' bash {} \;

(GNU find は再帰的であり、ファイルによる制限が可能で、ファイル名によるフィルタリングが可能で、過剰なシェルを生成しないので気に入っています)

期待:

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

Exportdすると、インライン スクリプトで使用できるようになります。ここでも、まったくbash必要ありません。(できればよりスリムで高速な) スクリプトでも同様に機能します。また、ファイルごとに 1 つのシェルを実行する必要もありません。次のバリアントを使用して、インライン スクリプトにさらに多くのファイルを渡すことができます。bashsh-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。これは、GNU だけでなく、POSIX 準拠の実装であればどれでも動作するはずですfind。あなたの質問で POSIX に関係のない部分は、明らかにbash${1:offset}演算子だけです。これは Korn シェル演算子であり、POSIX には存在しませんsh

ファイル タイプを指定できる再帰的なファイル検索については、次も参照してくださいzsh

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

上記では、 は(通常のファイルのみ).と同等ですが、 は のように隠しファイルも含めることを意味します。find-type fDfind


ちなみに、一般的なケースでは次のようになります。

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

${#var}演算子と${var:offset}演算子は次のように機能するため、「yes」が出力されることは保証されません。文字、 ないバイト

たとえば、UTF-8 ロケールでは、aとの値が次の場合、 yes は出力されませんb

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

これらを使用すると、$c私の名前 ( Stéphane)がその文字$aの半分を含み、残りの半分は(2 文字と 1 バイトは有効な文字を形成しませんが、カウントされます)になります。é$b${#a}3

したがって、 ではなく に$dなります。phane$'\xa9phane'

ただし、 の特定のケースでは、システム ロケールで一般的に使用可能な文字セットのいずれにものエンコーディングを含むd=$a/$b以外の文字がないため、問題はありません。//

関連情報