私のホームディレクトリが次のようになるとしましょう。/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
。
答え1
並列ソリューションの使用
小型で高速なソリューションにはGNU Parallelを使用できます。
find . -type d -print0 | parallel -0 cd {}'&&' <command-name>
これは、スペースと改行文字を含むディレクトリ名にも絶対に機能します。これが何をするかは、各ディレクトリparallel
から出力を取得してから。その後、ディレクトリの変更が成功すると、このディレクトリで別のコマンドが実行されます。find
{}
whileループを使用する一般的なソリューション
find "$PWD" -type d | while read -r line; do cd "$line" && <command-name>; done;
$PWD
変数には以下が含まれているため、ここではこれが使用されます。絶対パスコマンドが実行される現在のディレクトリ。絶対パスを使用しないと、cd
whileループでエラーが発生する可能性があります。
これはより簡単な解決策です。ディレクトリ名に奇妙な文字(改行文字など)が含まれていない限り、ほとんどの場合動作します(コメントを参照)。
答え2
この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.
答え3
他の答えの1つは次のとおりです。
探す。 -type d -exec sh -c 'cd "$0" &&ガイドライン'{}\;
(cd
コマンドは成功した場合にのみ実行されます。)一部の人は、見つかったディレクトリ({}
)が次に移動するようにダミーパラメータを挿入することを提案しました$1
。
探す。 -type d -exec sh -c 'cd "$1" &&ガイドライン'foo{}";"
もちろん、ここでは代わりに任意の文字列を使用できますfoo
。一般的な選択には-
、--
とが含まれますsh
。この文字列はエラーメッセージ(存在する場合)に使用されます。たとえば、次のようになります。
foo: 行 0: cd:制限されたディレクトリ:権限が拒否されました
だからsh
良い選択のようです。
\;
そして";"
それは絶対に同じです。それはスタイルの好みだけです。
上記のコマンドは、各ディレクトリに対して一度シェルを実行します。これにより、わずかなパフォーマンスが低下する可能性があります(特に実行するコマンドが比較的軽い場合)。代替案は次のとおりです。
探す。 -type d -exec sh -c 'd;do(cd "$d"&&ガイドライン);完了 'sh{}+
シェルは一度実行されますが、各ディレクトリに対して1回分岐します。
探す。 -type d -exec sh -c 'save_d=$PWD;実行cd "$d" &&ガイドライン; cd "$save_d";完了 ' sh {} +
サブシェルを作成しません。あなたの質問が示すように、絶対パスを検索する場合は、上記の内容を組み合わせて実行できます。
d;execute cd "$d" && の /home/test -type d -exec sh -c ' を探します。ガイドライン;完了' sh {} +
サブシェルを作成せず、開始点を保存しません。
答え4
このようなものを使用できます
find /home/test/ -type d -exec bash -c '<Command to be executed>' \;
例:
次のコマンドは、pwdコマンドの実行と同様にディレクトリ名を表示します。
find /home/test/ -type d -exec bash -c 'echo $0' \;