再帰ディレクトリにある.cで終わるすべてのファイルの名前を変更します。

再帰ディレクトリにある.cで終わるすべてのファイルの名前を変更します。

ディレクトリとサブディレクトリのファイル名(.cファイル)にいくつかの文字列を追加するシェルスクリプトが必要です。

たとえば、lokesh親ディレクトリ、その中にある場合は、サブディレクトリ、内部(、...)、内部(、...)lokesh1です。したがって、スクリプトを実行した後、これを(、...)、...)に変更したいと思います。lokesh2lokesh11.c2.clokesh2a.cb.cx_1.cx_2.c(x_a.c, x_b.c

答え1

メモ:以下を作成しながらOpenBSDを使用しており、見つかったファイルのデフォルト名に置き換えられますfind。 GNUの場合、これは見つかったファイルのデフォルト名でもありますが、プレフィックスが追加され、以下の最初のコマンドが役に立たなくなります。 GNUユーザー(Linuxを使用しているほとんどの人と同様)の場合は、下にスクロールしてソリューションの他のバリエーションを見つけてください。-execdir utility {} ';'{}find{}./findfind


名前の前に。この付いたディレクトリの中.cや下のすべてのファイルを探そうとします。lokeshx_

find lokesh -type f -name '*.c' -execdir echo mv {} x_{} ';'

-type fそして式は-name '*.c'関連するすべてのファイルを見つけ、見つかった-execdir mv {} x_{} ';'ファイルの名前を変更します。

この-execdir式は標準ではありませんが、ほとんどの実装でfindこれをサポートしています。-exec指定されたユーティリティが、見つかったパス名の親ディレクトリを作業ディレクトリとして使用して実行されるという点で異なります。したがって、コマンドラインの内容は、名前を変更する{}ファイルのデフォルト名になります(たとえば、フルパス名ではありません-exec)。

一度実行し、echo正しい操作が行われたことを確認したら削除します。これにより、ファイル名が実際に変更されるのをecho防ぐことができます。mv


サポートされていないシステム-execdir(またはOpenBSDと同じではありません-execdir):

find lokesh -type f -name '*.c' \
    -exec sh -c 'for name do echo mv "$name" "${name%/*}/x_${name##*/}"; done' sh {} +

または、より短いが少し効率が低い。

find lokesh -type f -name '*.c' \
    -exec sh -c 'echo mv "$1" "${1%/*}/x_${1##*/}"' sh {} ';'

両方のバリアントは、基本的に同じことを行う短いシェルスクリプトを使用します。

mv "$name" "${name%/*}/x_${name##*/}"

これにより、フルパス名のファイルが$nameプレフィックスが付いた同じディレクトリの新しい名前に移動されます。x_パラメータ置換はパス名の親ディレクトリ${name%/*}と同じで、パス名のデフォルト名(ファイル名部分)を提供します。$( dirname "$name" )${name##*/}$( basename "$name" )

答え2

可能であれば、Perlの名前変更を使用できます。 Perl で名前を変更するとは、 rename.ul ではなく prename または file-rename を意味します。これはrenameシステムを指す可能性があり、以下に提案されているコードパラメータで使用しようとすると間違いがあります。

rename私のシステムでは(Ubuntu 17.10 - Perlの名前を変更するためにパッケージをインストールしました):

$ readlink -e $(type -P rename)
/usr/bin/file-rename

これが私がこの答えをテストする唯一の環境です!

例のように2つのディレクトリレベルしかない場合は、lokesh次のようにディレクトリから実行できます。

rename -n 's|/|/x_|' */*.c

常に-nこのフラグを最初に使用して実行してください。このフラグはなしで実行した場合に表示されます-n。正しい結果が表示されたら、それを削除してください-n

ディレクトリ構造が複雑な場合は、可能であれば再帰ワイルドカードを使用できます。大きな打撃を受けた場合:

shopt -s globstar

次に、次のことを試してくださいrename

rename -n 's|(.*)/|$1/x_|' ./**/*.c

これは最後のパス要素より前のすべてをキャプチャし、逆(.*)/参照を使用してそれを再生成します$1

そうでない場合(再帰ワイルドカードが利用できない場合)、次を使用してくださいfind

find . -type f -name "*.c" -exec rename -n 's|(.*)/|$1/x_|' {} +

ファイルが多くのディレクトリにある場合は遅くなりますが、より単純な正規表現を可能にするファイルを使用することもできます(-execdir〜175個のディレクトリで(1秒未満)ファイルと(3〜4秒)〜1113個のファイルの間に顕著な速度差があります。が見つかりました)):-exec-execdir.c

find . -type f -name "*.c" -execdir rename -n 's|/|/x_|' {} +

結果が-n少し混乱しているように見えますが、デフォルトの-execdir名前が正しく表示されたら大丈夫です。

しかし、おかげでクサラナンダの口コミ、私はこれがfindすべての-execdirパラメータがで始まるGNUバージョンに依存していることに気づきました./。 OpenBSDのバージョンはそうではありません。ファイル名にパスプレフィックスがまったくない場合は、次のバージョンを使用できます。

find . -type f -name "*.c" -execdir rename -n -- 's|^|x_|' {} +

ただし、OpenBSDがないためテストできませんfind

しかし、エリア・ケーガンとても役に立つこのより良い正規表現を思い出しました。find使用する実装と使用するか-execどうかに関係なく動作し、再帰-execdirワイルドカードとも動作します。

rename -n 's|[^/]+$|x_$&|'

/これは、パスの終わりにない少なくとも1つの文字と一致し()を追加した後、完全一致を再現します()。このコマンド$$&x_しなければならないどこでも動作し、findPerlを使用して名前を変更できます。

find . -type f -name "*.c" -exec rename -n 's|[^/]+$|x_$&|' {} +

関連情報