web-dev-qa-db-ja.com

ドット文字を含むファイル名で機能する、特定の拡張子を持つファイルを除くすべてのファイルに一致するBashグロビング

私はオーディオファイルを使っていくつかのことをしていますが、それらのほとんどはmp3ファイルではありません。ここで、mp3ファイルではないファイル、または.mp3拡張子のないファイルのみでいくつかのコマンドを実行したいと思います。

私自身は正規表現はかなり得意だと思いますが、予期しない点で微妙に異なるファイルグロビングはあまり得意ではありません。

私は周りを見回して他から学んだSO&SEはBashにこれを可能にする「拡張グロビング」があると答えます:

file ../foo/bar/*.!(mp3)

しかし、私のファイル名の一部には、ファイル名拡張子を形成するもの以外にドットが含まれています。

../foo/bar/Naked_Scientists_Show_19.10.15.mp3
../foo/bar/YWCS_ep504-111519-pt1_5ej4_41cc9320.mp3_42827d48daefaa81ec09202e67fa8461_24419113.mp3
../foo/bar/eLife_Podcast_19.09.26.mp3
../foo/bar/gdn.sci.080428.bg.science_weekly.mp3

グロブは最後のドットからではなく、最初のドットから一致しているようです。ドキュメントを見ましたが、正規表現ほど強力ではないようです。しかし、* nixシェルにそれほど多くの時間を費やさなかったので、私はすべてを実際に苦労しませんでした。

Bashグロビングでこれを行うことができるいくつかの方法を見逃しましたか?そうでない場合でも、findまたは他のツールを使用して同じことを実現する方法は、知っておく価値があります。

10
hippietrail

*.!(mp3)は_foo.bar.mp3_に一致します。これは、_foo._の後に_bar.mp3_が続く_mp3_ではないためです。

ここで!(*.mp3)が必要です。これは、_.mp3_で終わらないものに一致します。

名前に少なくとも1つの_._(非表示のファイルになる先頭のファイルを除く)が含まれているが_.mp3_で終わっていないファイルを照合する場合は、!(*.mp3|!(*.*))

18

GLOBIGNORE変数 もあります:

GLOBIGNORE Shell変数を使用して、パターンに一致するファイル名のセットを制限できます。 GLOBIGNOREが設定されている場合、GLOBIGNOREのパターンの1つとも一致する各一致ファイル名は、一致のリストから削除されます。 nocaseglobオプションが設定されている場合、GLOBIGNOREのパターンに対する照合は、大文字と小文字を区別せずに実行されます。ファイル名.および..は、GLOBIGNOREが設定されていてnullでない場合は常に無視されます。ただし、GLOBIGNOREをnull以外の値に設定すると、dotglobシェルオプションが有効になるため、「.」で始まる他のすべてのファイル名が一致します。 「.」で始まるファイル名を無視するという以前の動作を得るには、「.*」をGLOBIGNOREのパターンの1つにします。 dotglobが設定されていない場合、GLOBIGNOREオプションは無効になります。

$ touch a.b.mp3 .c.mp3 foo.tgz .bar
$ echo *
a.b.mp3 foo.tgz
$ shopt -s extglob; echo *.!(mp3)
a.b.mp3 foo.tgz
$ GLOBIGNORE='*.mp3'; echo *
.bar foo.tgz
6
muru

私が考えることができる最も簡単な方法:

find ${path-to-folder} -type f  | grep -vE ".*\.mp3$"

フォルダー内のすべてのファイルを見つけ、それを逆拡張grepにパイプします。

場所内のすべてのファイルを検索する

find ${path-to-folder} -type f 

Grepを逆にし、正規表現を使用して拡張子でフィルタリングする

grep -vE ".*\.mp3$"

Grepフラグ:

  • -v逆grep

  • -E拡張grep(正規表現の使用)

正規表現は説明しました:

  • .*は、0から任意の文字数、任意の可能な文字までを意味します

  • \.実際のドットを探します

  • mp3は、拡張子を形成する文字列

  • $はEOLを表します

2
Kramer

おそらくあなたの状況には理想的ではありませんが、純粋なBashで関数を作成し、拡張機能を引数として渡して、bashrcに追加したい場合に便利な方法を考えていました。次のように、将来同じことをしたい

したがって、基本的には、目的の拡張子の正規表現チェックです。

for file in *; do
  if [[ $file =~ \.mp3$ ]]; then
    echo $file
  fi
done

これを関数に実装すると、現在のディレクトリにある特定の拡張子を持つすべてのファイルが出力されます。

getFileByExt(){
local extension="$1"
if (( $# == 1 )); then
for file in *; do
  if [[ $file =~ \.$extension$ ]]; then
    echo $file
  fi
done
else
  echo "Usage: ${FUNCNAME[0]} <extension>" 
## If run from bashrc, return the name of function
fi
}

たとえば、mp3拡張子が付いたすべてのファイルを取得するには、次のように簡単です。

getFileByExt mp3

そして、特定の拡張子のないファイルを取得するには:これは、現在のディレクトリで特定の拡張子を持たないすべてのファイルを出力します。

getFileWithoutExt(){
local extension="$1"
if (( $# == 1 )); then
for file in *; do
  if [[ ! $file =~ \.$extension$ ]]; then
    echo $file
  fi
done
else
  echo "Usage: ${FUNCNAME[0]} <extension>"
fi
}

同様に、mp3拡張子のないファイルを取得するには、次のようにします。

getFileWithoutExt mp3

詳細:

https://stackoverflow.com/questions/407184/how-to-check-the-extension-of-a-filename-in-a-bash-script

https://stackoverflow.com/questions/18278990/easiest-way-to-check-for-file-extension-in-bash/1828035

1
Rakib Fiha