web-dev-qa-db-ja.com

文字列が一致するファイルを含むディレクトリパスを抽出します

ファイルresults.outを含む複数のレベルに複数のサブディレクトリがあります

./dir1/results.out
./dir2/dir21/results.out
./dir3/dir31/dir311/results.out

次に、string1results.outを検索し、results.outを含むstring1のディレクトリパスを抽出する必要があります。これらのサブディレクトリを別の場所に移動する必要があるためです。 。たとえば、次のコードを使用してファイルパスを取得できます

for i in $(find . -type f -name "results.out);
do
grep -l "string1" $i
done

上記のコードを変更して、ディレクトリパスのみを取得するにはどうすればよいですか?

2
WanderingMind

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'
5
steeldriver

zshの場合:

print -rl ./**/results.out(.e_'grep -q string $REPLY'_:h)

これにより、通常のファイルが再帰的に検索されます(.)名前付きresults.out、実行grep -q ...それぞれに、そのevaluates trueの場合、パス(最後の要素のないパス)のheadのみを出力します。


findおよびshを使用する別の方法で、パラメーター展開を使用してヘッドを抽出します。

find . -type f -name results.out -exec grep -q string {} \; \
-exec sh -c 'printf %s\\n "${0%/*}"' {} \;
4
don_crissti
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
1
MelBurslan

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_に移動されるようにします。 __。

1

私が正しく理解したと仮定すると、あなたはまさにそれをしたいのです:

find . -type f -name "results.out" -exec grep -l "string1" {} \; | xargs dirname

最初の部分は一致するファイル名を取得し、次にxargsはそれらを引数としてdirnameプログラムに渡し、パスからファイル名を「削除」します

0
Magik6k