web-dev-qa-db-ja.com

いくつかのロジックを含むファイルの名前を変更するツール

文字列または文字列のセットがまだ含まれていないファイルの名前を変更して、その文字列を含めるコマンドラインツールはありますか?

したがって、特定のフォルダ内のすべてのファイルには、「高優先度」の名前にhighが含まれている必要がありますが、そうでないものもあります。すべてのファイルに追加するのではなく、ファイルの名前にhighが含まれているかどうかを最初に確認し、含まれていない場合は、名前の先頭に追加するにはどうすればよいですか?

2
user3645925

bashを使用している場合、high Shellオプションが設定されていれば、パターン!(*high*)は文字列extglobを含まない現在のディレクトリ内のすべての名前と一致します。

$ shopt -s extglob
$ ls
1      2      3      4-high
$ ls -d -- !(*high*)
1 2 3

次に、このパターンに一致する名前をループして、一致する各名前を変更します。

shopt -s extglob nullglob

for name in !(*high*); do
    [[ ! -f $name ]] && continue

    mv -- "$name" "high-$name"
done

ここで起こっていることは、ループの前にextglobnullglob(パターンが一致しない場合、グロブパターンをそのまま保持するのではなく非表示にする)を設定することです。非表示の名前の名前も変更する場合は、dotglobを有効にすることもできます。

次に、ループは通常のファイルを参照しない名前(たとえば、ディレクトリ名など)をスキップし、名前の先頭にmvを付けて文字列high-を挿入します。

mvコマンドの--は、ダッシュで始まるファイル名を誤ってオプションのセットとして解釈しないようにするためのものです。

これを一連のテストファイルで実行します。

$ ls
1      2      3      4-high

上から直接シェルにコードを貼り付けるだけです。

$ shopt -s extglob nullglob
$
$ for name in !(*high*); do
>     [[ ! -f $name ]] && continue
>
>     mv -- "$name" "high-$name"
> done
$ ls
4-high high-1 high-2 high-3

Perlのrenameユーティリティを次のように使用することもできます。

shopt -s extglob
rename -v 'if (-f) { s/^/high-/ }' -- !(*high*)

これにより、この回答の最初のバリエーションのループの-fテストがPerlに移動しますが、同じファイル名グロビングパターンを使用して、名前を変更するファイルを選択します。 -fにより、名前の変更は通常のファイルにのみ影響します(ディレクトリなどは影響しません)。


シェルの拡張グロブパターンに依存しないバリエーションは、

rename -v 'if (-f && !/high/) { s/^/high-/ }' -- *

これは、名前にhigh呼び出し内に文字列renameがすでに含まれているかどうかのテストを実行し、含まれている場合はファイルの名前変更をスキップします。 * globは、現在のディレクトリ内のすべてのファイルを選択します(非表示のファイルを除く)。

1
Kusalananda

GNU Parallelがある場合:

parallel mv {} '{= /high/ or $_="high$_" =}' ::: *
1
Ole Tange

zshの場合:

autoload zmv # best in ~/.zshrc
zmv '^*high*' 'high-$f'

大文字と小文字を区別しないマッチングの場合:

zmv '^*(#i)high*' 'high-$f'
1