複数のディレクトリレベルを確実にトラバースするためのコマンドライン

複数のディレクトリレベルを確実にトラバースするためのコマンドライン

質問と同じ問題があります ファイル拡張子が欠落している音楽ファイルの名前を変更する @Gilles が提供してくれたスクリプトは非常に勉強になりましたが、残念ながら期待通りには動作しませんでした。私が探していたのは、「/path/to/music/directory/」以下のすべてのサブディレクトリ、すべてのレベルにある、拡張子のないすべての音楽ファイルにファイル拡張子を追加するスクリプトでした。提案されたコマンドラインパラメータは

/path/to/music/directory/{**/,}*

スクリプトは、"/path/to/music/directory/" の 1 レベル下のサブディレクトリ内のすべてのファイルを調べますが、それより下のレベルは調べません。"directory/" より下のすべてのレベルのすべてのファイルを走査するには、どのコマンド ライン パラメータを使用すればよいですか?

また、以下のドキュメントへのリンクもいただければ幸いです。

{**/,}* 

一部。

ところで、元の回答に興味がある人のために。私は行を変更した後、スクリプトがよりうまく機能することを発見しました

file -i "$@" |

file --mime-type "$@" | 

(もし私に権限レベルがあったら、元の回答にコメントとしてこれを記載していたでしょう)

答え1

bashglobstarオプションを有効にするだけでいいと思います。デフォルトでは有効になっていないからです。ウブントゥ以下に説明します。

式には/path/to/music/directory/{**/,}*2 つの展開構造が含まれています。1 つは中括弧展開で、もう 1 つはパス名展開です。

ブレース拡張

ブレース拡張は例で説明するのが最も適切です:

$ printf '%s\n' before-{a,bb,1,22}-after
before-a-after
before-bb-after
before-1-after
before-22-after

(ここでも以下でも、 にprintf '%s\n' item1 item2 etc..似ていますechoが各要素を新しい行に出力するコマンドを使用しました)

中括弧内のコンマで区切られた各要素が展開された要素になることがわかります。

元の例では、括弧内に要素**/と空の要素が含まれており、次のように展開されます。

$ printf '%s\n' /path/to/music/directory/{**/,}*
/path/to/music/directory/**/*
/path/to/music/directory/*

グロブスター

ここで、bash globについて見てみましょう**。これは、bash マニュアルページは、どちらもシェル オプションに関連しておりglobstar、意味は次のとおりです。

パス名拡張コンテキストで使用されるパターン ** は、ファイルと 0 個以上のディレクトリおよびサブディレクトリに一致します。

このシェルオプションはアクティブUbuntuのデフォルト:

$ shopt globstar
globstar        off

有効化するには

shopt -s globstar

(shopt -u globstar無効にするには使用します)。

次のようなディレクトリ構造があるとします。

$ find first/ | sort
first/
first/aaa
first/second
first/second/bbb01
first/second/bbb02
first/second/third
first/second/third/ccc1
first/second/third/ccc2
first/second/third/ccc3

次のような展開が考えられます。

$ printf '%s\n' first/**/a*
first/aaa

$ printf '%s\n' first/**/b*
first/second/bbb01
first/second/bbb02

$ printf '%s\n' first/**/c*
first/second/third/ccc1
first/second/third/ccc2
first/second/third/ccc3

**つまり、パス名要素以上に拡張できることがわかります。

答え2

私はこんなことをするだろう

#! /bin/bash

[[ -d "$1" ]] || { echo "$1 not a directory, exiting..."; exit 1; }

find "$1" -type f | while read F; do
  # do what you want with the "$F"
done

exit 0

そしてスクリプトを呼び出します./my_script <directory>

関連情報