私のメインディレクトリが/home/test
だとしましょう
その下にはたくさんのサブディレクトリがあり、サブディレクトリの下にはまだたくさんのサブディレクトリがあります。
例:
/home/test
/home/test/subdir1
/home/test/subdir1/subdir2
/home/test/subdir1/subdir2/subdir3
/home/test/subdir1/subdir2/subdir4
/home/test/subdir1/subdir2/subdir4/subdir5
等々 ...
各ディレクトリを取得し、pwd
コマンドを実行するだけの簡単なスクリプトが必要です。
GNU Parallelを使用すると、コンパクトで高速なソリューションを実現できます。
find . -type d -print0 | parallel -0 cd {}'&&' <command-name>
これは、スペースと改行を含むディレクトリ名の場合でも、まったく問題なく機能します。ここでparallel
が行うことは、すべてのディレクトリであるfind
から出力を取得し、それを{}
を使用してcdにフィードすることです。次に、ディレクトリの変更が成功すると、このディレクトリの下で別のコマンドが実行されます。
find "$PWD" -type d | while read -r line; do cd "$line" && <command-name>; done;
$PWD
がここで使用されていることに注意してください。これは、その変数に、コマンドが実行されている現在のディレクトリの絶対パスが含まれているためです。絶対パスを使用しない場合、cd
はwhileループでエラーをスローする可能性があります。
これはより簡単な解決策です。ディレクトリ名に改行のような奇妙な文字が含まれている場合を除いて、ほとんどの場合機能します(コメントを参照)。
find
コマンドは強力ですが、それを使用するのは少し難しいです。
必要なことを実行できると確信しています。以下のこのコマンドは、「ほぼ」あなたが求めているものです。
find . -type d -execdir pwd \;
ただし、これは最も深いディレクトリレベルではコマンドを実行しません。他のディレクトリが見つかったディレクトリで実行されます。
したがって、subdir4
が含まれているため、subdir5
で実行されます。しかし、subdir5
にはありません-おそらくご想像のとおりです。
よく知られている-execdir
ではなく、-exec
オプションを使用することが重要です(man find
を参照)。
-exec
オプションは、開始ディレクトリでコマンドを実行しますが、他にも欠点があります。
-exec command ;
Execute command; true if 0 status is returned. All following
arguments to find are taken to be arguments to the command until
an argument consisting of ';' is encountered. The string '{}' is
replaced by the current file name being processed everywhere it
occurs in the arguments to the command, not just in arguments
where it is alone, as in some versions of find. Both of these
constructions might need to be escaped (with a \ ) or quoted to
protect them from expansion by the Shell. See the EXAMPLES sec‐
tion for examples of the use of the -exec option. The specified
command is run once for each matched file. The command is exe‐
cuted in the starting directory. There are unavoidable security
problems surrounding use of the -exec action; you should use the
-execdir option instead.
しかし、オプション-execdir
はまさにあなたが求めるものです:
-execdir command ;
-execdir command {} +
Like -exec, but the specified command is run from the subdirec‐
tory containing the matched file, which is not normally the
directory in which you started find. This a much more secure
method for invoking commands, as it avoids race conditions during
resolution of the paths to the matched files. As with the -exec
action, the '+' form of -execdir will build a command line to
process more than one matched file, but any given invocation of
command will only list files that exist in the same subdirectory.
If you use this option, you must ensure that your $PATH environ‐
ment variable does not reference '.'; otherwise, an attacker can
run any commands they like by leaving an appropriately-named file
in a directory in which you will run -execdir. The same applies
to having entries in $PATH which are empty or which are not abso‐
lute directory names.
他の答えの1つはこれに近づきました:
見つける。 -type d -exec sh -c'cd "$ 0" && cmd'{} \;
(cd
が成功した場合にのみコマンドを実行します)。ダミーの引数を挿入することをお勧めする人もいるので、見つかったディレクトリ({}
)スライドして$1
:
見つける。 -type d -exec sh -c'cd "$ 1" && cmd'foo {} ";"
もちろん、ここではfoo
の代わりに任意の文字列を使用できます。一般的な選択肢には-
、--
、およびsh
。この文字列は、エラーメッセージ(存在する場合)で使用されます。例:
foo:行0:cd: 制限付きディレクトリ: アクセス拒否
したがって、sh
は良い選択のようです。 \;
および";"
は完全に同等です。それは単なるスタイルの好みです。
上記のコマンドは、ディレクトリごとに1回シェルを実行します。これには、パフォーマンスが低下する可能性があります(特に、実行するコマンドが比較的軽量の場合)。代替案が含まれます
見つける。 -type d -exec sh -c'for d; do(cd "$ d" && cmd);完了 'sh {} +
これはシェルを1回実行しますが、ディレクトリごとに1回フォークし、
見つける。 -type d -exec sh -c'save_d = $ PWD; dの場合; cd "$ d" &&を実行します cmd; cd "$ save_d";完了 'sh {} +
サブシェルを生成しません。あなたの質問が示唆するように、あなたが絶対的な道を探しているなら、あなたは上記を組み合わせてすることができます
dの/ home/test -type d -exec sh -c 'を検索します。 cd "$ d" &&を実行します cmd;完了 'sh {} +
サブシェルを生成せず、開始点を保存する必要もありません。
追加のpwd
コマンドを実行する必要はなく、次のコマンドを実行できます。
find test/ -type d
ディレクトリをtest/
に置き換えることができます
あなたはこのようなものを使うことができます
find /home/test/ -type d -exec bash -c '<Command to be executed>' \;
例:
以下のコマンドは、pwdコマンドの実行と同様に、dirnameを表示します。
find /home/test/ -type d -exec bash -c 'echo $0' \;