ディレクトリとサブディレクトリのファイル名(.cファイル)にいくつかの文字列を追加するシェルスクリプトが必要です。
たとえば、lokesh
親ディレクトリ、その中にある場合は、サブディレクトリ、内部(、...)、内部(、...)lokesh1
です。したがって、スクリプトを実行した後、これを(、...)、...)に変更したいと思います。lokesh2
lokesh1
1.c
2.c
lokesh2
a.c
b.c
x_1.c
x_2.c
(x_a.c,
x_b.c
答え1
メモ:以下を作成しながらOpenBSDを使用しており、見つかったファイルのデフォルト名に置き換えられますfind
。 GNUの場合、これは見つかったファイルのデフォルト名でもありますが、プレフィックスが追加され、以下の最初のコマンドが役に立たなくなります。 GNUユーザー(Linuxを使用しているほとんどの人と同様)の場合は、下にスクロールしてソリューションの他のバリエーションを見つけてください。-execdir utility {} ';'
{}
find
{}
./
find
find
名前の前に。この付いたディレクトリの中.c
や下のすべてのファイルを探そうとします。lokesh
x_
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_
しなければならないどこでも動作し、find
Perlを使用して名前を変更できます。
find . -type f -name "*.c" -exec rename -n 's|[^/]+$|x_$&|' {} +