質問: シェルスクリプト 初心者のものです。下記のようにシェルコマンドを実行すると、カレントディレクトリ以下に存在する「word」ディレクトリを再帰的に探してきてくれます(いくらディレクトリ構造が深くても、ちゃんとカレントディレクトリ以下のwordディレクトリのパスを全て取ってきてくれて助かっています) ``` find ./ -name "*word" -type d ``` 上記のコマンドを実行してwordディレクトリが見つかった後の処理をシェルスクリプト として書きたいと思っています。カレントディレクトリ下のwordディレクトリの中にある、ファイルだけ取得したいという書き方を、シェルスクリプト だとどのように書くのでしょうか。 流れとしては下記のような感じです ``` 1 カレントディレクトリ以下に存在する「word」ディレクトリを再帰的に探す 2 もし「word」ディレクトリが見つかったら、その中を調査 3 指定した条件にマッチするファイルがあればそれを取得 ```
回答: 標準的な方法については既にコメントがあるので、ちょっと変化球を投げてみます。 ### find2perl でperlスクリプトやシェルスクリプトを呼び出す find2perlは、findコマンドを模倣したコマンドライン書式を受け取り、findするかわりに、その機能をもつperlスクリプトを生成するスクリプトです。 このスクリプトの中を少し書き換えて、シェルスクリプトを下請けに呼び出すことができます。 まず、次のようにして雛形スクリプトを得ます。 ``` $ find2perl ./ -name "*work" -type d > test.pl ``` このtest.plをエディタで開くと、最後が次のようになっています。 ``` (前略) sub wanted { my ($dev,$ino,$mode,$nlink,$uid,$gid); /^.*work\z/s && (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && -d _ && print("$name\n"); } ``` findの書式に従い、wanted関数の内容は見つかったファイルの名前を出力するものとなっています。 これを目的に合わせて加工します。 $nameに見つかったファイル名、$dirに検索対象のディレクトリ名(-dで指定したもの)が代入されているので、これを活用してperlで処理してもいいし、 system()を利用して、見つかったファイルごとにシェルスクリプトを呼び出すこともできます。 以下は、findされたディレクトリ下の*.txtをシェルを通してリストアップしてみた例です。 ``` (前略) sub wanted { my ($dev,$ino,$mode,$nlink,$uid,$gid); /^.*work\z/s && # ファイル名での選択条件が正規表現で書かれている。拡張正規表現を使って、超絶複雑な条件設定にレベルアップすることもできる。 (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && # 必要なら各種ファイル属性情報も利用できる -d _ && system(qq( ls $name/*.txt )) #qq()の間にシェルスクリプトを普通に書ける。'や"のエスケープも必要ない。 } ``` ### bash/shのかわりにzshを使う zsh最強。 たとえば、カレントディレクトリ以下で名前がworkで終わるサブディレクトリ下の*.txtを列挙したいなら、下の一行でOKです。 ``` ls ./**/*work/*.txt ```