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
エクスポートすると、d
インラインスクリプトで使用できますbash
。bash
ここではまったく必要ありません。あなたの(希望により薄く/より速い)sh
製品も同じことをします。また、各ファイルに対してシェルを実行する必要はありません。次のバリアントを使用して、より多くのファイルをインラインスクリプトに渡すことができます-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
。これはfind
GNU実装だけでなく、すべてのPOSIX準拠の実装でも機能します。あなたの質問でPOSIX以外の唯一の部分は、POSIXの演算子ではなくKornシェル演算子ですbash
。${1:offset}
sh
ファイルの種類を指定できる再帰的なファイル検索については、以下も参照してくださいzsh
。
(cd -P -- "$d" &&
for file (**/*(ND.)) {
dir=$file:h
printf '%10s: %s\n' relative $file reldir $dir
})
上記は、's(通常のファイルのみ.
)と同じですが、隠しファイルを含む場合でも同様です。find
-type f
D
find
参考までに、一般的には次のようになります。
c=$a$b; d=${c:${#a}}
[ "$b" = "$d" ] && echo yes
${#var}
and${var:offset}
演算子は次のようになるため、「yes」出力は保証されません。数値、いいえバイト。
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
問題はありません。/
/