私は自分のbash(最新のUbuntu LTSリリース)を使ってディレクトリとそのサブディレクトリ内の特定の拡張子を持つすべてのファイルを見つけようとしています。
これはスクリプトファイルに書かれているものです:
#!/bin/bash
directory="/home/flip/Desktop"
suffix="in"
browsefolders ()
for i in "$1"/*;
do
echo "dir :$directory"
echo "filename: $i"
# echo ${i#*.}
extension=`echo "$i" | cut -d'.' -f2`
echo "Erweiterung $extension"
if [ -f "$i" ]; then
if [ $extension == $suffix ]; then
echo "$i ends with $in"
else
echo "$i does NOT end with $in"
fi
Elif [ -d "$i" ]; then
browsefolders "$i"
fi
done
}
browsefolders "$directory"
残念ながら、このスクリプトをターミナルで起動すると、次のようになります。
[: 29: in: unexpected operator
($extension
の代わりに'in'
を使う)
ここで何が起こっていますか、エラーはどこにありますか?しかし、この中括弧
find $directory -type f -name "*.in"
それよりも少し短い(そしてより安全である - ファイル名とディレクトリ名の中の空白を扱う)。
あなたのスクリプトはおそらく名前に.
を持たないエントリに失敗し、$extension
を空にします。
find {directory} -type f -name '*.extension'
example 現在のディレクトリとそのサブディレクトリにあるすべてのcsvファイルを検索する
find . -type f -name '*.csv'
私が使用する構文は、@ Mattが提案したものとは少し異なります。
find $directory -type f -name \*.in
(それは1つ少ないキーストロークです)。
find
を使わないで:
du -a $directory | awk '{print $2}' | grep '\.in$'
browsefolders ()
の後に{
がありません$in
は$suffix
であるべきですcut
の行は、front.middle.extension
の中央部分だけを取得します。あなたは${varname%%pattern}
とその友達についてあなたのシェルマニュアルを読むべきです。私はあなたがこれをシェルスクリプティングの練習として行うと仮定します、さもなければ既に提案されたfind
解決策は進むべき道です。
スクリプトを実行せずに適切なシェル構文をチェックするには、sh -n scriptname
を使用します。
現在のディレクトリにあるすべてのpom.xml
ファイルを見つけて印刷するには、次のようにします。
find . -name 'pom.xml' -print
ここではfind
コマンドを使用すると便利ですが、シェル自体がサードパーティ製ツールなしでこの要件を達成するためのオプションを提供します。 bash
シェルは拡張グロブサポートオプションを提供し、それを使用して必要な拡張子に一致する再帰パスの下でファイル名を取得できます。
拡張オプションはextglob
で、これは以下のようにshopt
オプションを使用して設定する必要があります。オプションは-s
サポートで有効になり、-u
フラグで無効になります。さらに、いくつかのオプションを使用することもできます。つまり、比類のないグロブが完全に一掃され、ゼロワードのセットに置き換えられるというnullglob
です。そしてglobstar
は全てのディレクトリを通して再帰することを可能にします
shopt -s extglob nullglob globstar
さて、あなたがする必要があるのは、あなたが以下のようにすることができる特定の拡張子のファイルを含むようにglob表現を形成することです。正しく引用され展開されると、特殊文字を含むファイル名はそのまま残り、シェルによる単語分割のために壊れることはないので、配列を使用します。
たとえば、再帰パス内のすべての*.csv
ファイルをリストするには
fileList=(**/*.csv)
オプション**
はサブフォルダを再帰的に検索することであり、*.csv
は言及された拡張子の任意のファイルを含めるためのglob展開です。実際のファイルを印刷するためには、
printf '%s\n' "${fileList[@]}"
シェルスクリプトで使用する場合、配列を使用して適切な引用符で囲まれた展開を行うのが正しい方法ですが、対話的に使用する場合は、glob式を指定してls
を使用することができます。
ls -1 -- **/*.csv
これは、複数のファイル、つまり複数の拡張子で終わるファイルに一致するように拡張することができます(つまり、find
コマンドに複数のフラグを追加するのと同じです)。たとえば、すべての再帰的な画像ファイル、すなわち拡張子*.gif
、*.png
、および*.jpg
を取得する必要がある場合を考えてみましょう。
ls -1 -- **/+(*.jpg|*.gif|*.png)
これは否定的な結果もあるように非常にうまく拡大することができます。同じ構文で、globの結果を使用して特定の種類のファイルを除外することができます。上記の拡張子を持つファイル名を除外したいとします。
excludeResults=()
excludeResults=(**/!(*.jpg|*.gif|*.png))
printf '%s\n' "${excludeResults[@]}"
コンストラクト!()
は、内部にリストされているファイル拡張子を含まない否定演算子です。また、|
は、グロブのOR一致を実行するためにExtended Regular Expressionsライブラリで使用されるのと同じ代替演算子です。
これらの拡張されたglobサポートはPOSIX bourneシェルでは利用できず、最近のバージョンのbash
に純粋に固有のものです。ですから、POSIXシェルとbash
シェルをまたいで実行されるスクリプトの移植性を考えているのであれば、このオプションは正しくありません。
find $directory -type f -name "*.in"|grep $substring
for file in "${LOCATION_VAR}"/*.Zip
do
echo "$file"
done
find "$PWD" -type f -name "*.in"