ファイルresults.outを含む複数のレベルに複数のサブディレクトリがあります
./dir1/results.out
./dir2/dir21/results.out
./dir3/dir31/dir311/results.out
次に、string1
でresults.out
を検索し、results.out
を含むstring1
のディレクトリパスを抽出する必要があります。これらのサブディレクトリを別の場所に移動する必要があるためです。 。たとえば、次のコードを使用してファイルパスを取得できます
for i in $(find . -type f -name "results.out);
do
grep -l "string1" $i
done
上記のコードを変更して、ディレクトリパスのみを取得するにはどうすればよいですか?
GNU find
がある場合は、%h
フォーマット指定子を使用してパスを出力できます
%h Leading directories of file's name (all but the last ele‐
ment). If the file name contains no slashes (since it is
in the current directory) the %h specifier expands to
".".
だから例えばあなたはすることができます
find . -name 'results.out' -exec grep -q 'string1' {} \; -printf '%h\n'
zsh
の場合:
print -rl ./**/results.out(.e_'grep -q string $REPLY'_:h)
これにより、通常のファイルが再帰的に検索されます(.
)名前付きresults.out
、実行grep -q ...
それぞれに、そのe
valuates trueの場合、パス(最後の要素のないパス)のh
eadのみを出力します。
find
およびsh
を使用する別の方法で、パラメーター展開を使用してヘッドを抽出します。
find . -type f -name results.out -exec grep -q string {} \; \
-exec sh -c 'printf %s\\n "${0%/*}"' {} \;
for i in $(find . -type f -name "results.out);
do
grep -l "string1" $i ; exitcode=${?}
if [ ${exitcode} -eq 0 ] # string1 is found in file $i
then
path=${i%/*}
echo ${path}
fi
done
GNUシステムの場合:
_ find . -depth -type f -name results.out -exec grep -lZ string1 {} + |
xargs -r0 dirname -z |
xargs -r0 mv -t /dest/dir
_
または:
_ find . -depth -type f -name results.out -exec grep -lZ string1 {} + |
LC_ALL=C sed -z 's|/[^/]*$||' |
xargs -r0 mv -t /dest/dir
_
_-depth
_は、_./A/results.out
_と_./A/B/results.out
_の両方が一致する場合、_./A/B
_が_/dest/dir/B
_に移動される前に、_./A
_が_/dest/dir/A
_に移動されるようにします。 __。
私が正しく理解したと仮定すると、あなたはまさにそれをしたいのです:
find . -type f -name "results.out" -exec grep -l "string1" {} \; | xargs dirname
最初の部分は一致するファイル名を取得し、次にxargsはそれらを引数としてdirnameプログラムに渡し、パスからファイル名を「削除」します