複数のディレクトリのファイル名を変更する

複数のディレクトリのファイル名を変更する

タイトルがファイル番号の前に表示されるため、ファイルの順序が正しくない複数のディレクトリがあります。拡張子を除くすべてのファイルを最後に一致させて置き換えたいので、数字は以下のように先頭にあります。

したがって;

A guide to perfect eggs-456704.mp4
Boil an egg-456702.mp4
How to ruin scrambled eggs-456703.mp4
Make green eggs and ham-456701.mp4
Poached eggs-456705.mp4

これに関して:

456701-Make green eggs and ham.mp4
456702-Boil an egg.mp4
456703-How to ruin scrambled eggs.mp4
456704-A guide to perfect eggs.mp4
456705-Poached eggs.mp4

スペースを持つ各ファイルには、任意のヘッダー長があります。数字は「.mp4」拡張子の前の6桁ですが、ヘッダーの後にはダッシュがあります。

答え1

使用findそしてShell (Bash, ksh, ksh93, mksh, zsh) Pattern substitution expansion

find * -type f -name "*.mp4" -exec bash -c 'echo mv -v "$1" "${1//[^0-9]}-${1//[\-0-9]}"' _ '{}' \;
  • 数字を除くすべてを削除${1//[^0-9]}します。 is は//グローバル代替構文で、/数字が最初に表示される場合にのみ使用されます。

  • 次に、ダッシュ/ハイフンを使用-して、aまたは数字である${1//[\-0-9]}すべての項目を削除します(ファイル名にaと数字の部分のみがあると仮定)。--

上記で使用したコマンドは-exec何らかの理由で安全ではありません。12ここでShell Substitution Expansionを使用すると、ファイルパスを使用して予期しない名前が変更され、-ファイル名のすべてのダッシュが削除されます。

echo最後に、テストの実行に使用された場所で実際の名前を変更するには、コマンドから上記の項目を削除することを忘れないでください。


find . -type f -name "*.mp4" -execdir sh -c '
    n="${1##*-}";fn="${1%-*}"; 
    echo mv -v "$1" "${n%.*}-${fn##*/}.mp4" ' _ '{}' \;

前と同じコマンドですが、ここでは次のように使用します。shell (POSIX sh/bash/Korn/zsh) parameter substitution expansionこれにより、削除する必要がある最後のダッシュを除いて、-ファイル名のすべてのダッシュがそのまま残ります(存在する場合)。a file-with -- here-006.file

-type f次に終わるファイルを探しています。つまり、現在のディレクトリを次に変更します。.mp4-execdirfind文書ディレクトリ自体内でsh -c '...'を探して実行します。

  • "cut-up-to-last-prefix"を使用:n="${1##*-}"ファイル名の先頭から最後のダッシュまですべてを削除し、変数に-割り当てるか、現在のディレクトリに戻る相対パス。-n$1${1}./fileName-execdir sh -c '...' _ '{}' \;

  • "cut-up-to-first-suffix"を使用:最初のダッシュとそれ自体が表示されるfn="${1%-*}"まで、ファイル名の末尾からすべてを削除して変数に割り当てます。--fn

    n="456704.mp4"nf="./A guide to perfect eggs"最初のファイルを想定)。それから;

  • 最初の点とそれ自体が表示される${n%.*}-まで、fileNameの末尾からすべてを削除し、ダッシュを追加します。したがって、これはfileNameの数値部分のみを生成します。..-456704

  • ${fn##*/}.mp4ファイル名の要求から最後の/スラッシュとそれ自体を確認し、最後に追加するまで/すべてを削除します。.mp4そのため、このような結果が出てくるのですA guide to perfect eggs.mp4


1 使用にはどのようなセキュリティ問題と競合状態がありますかfind -exec
2 PATHのディレクトリに "-execdir"操作を使用するのが安全ではないのはなぜですか?

答え2

これを行う方法は次のとおりです。未テスト

#!/bin/bash

files=(*file)

for f in "${files[@]}" 
  do 
     get_ext="${f##*.}"
     no_ext="${f%-*}"
     n="${f##*-}" nn="${n%.*}"
     mv "$f" "$nn-$no_ext.$get_ext"
 done

答え3

set "a file blah blah-004.file" \
"b file blah blah blah-002.file" \
"c file blahh blah-003.file" \
"d file blah blah blah blabby blah-001.file" \
"e file blah-005.file"

for name; do
  old=$name                 # save old name
  ext=${name##*.}           # take extension
  name=${name%.*}           # remove extension
  number=${name##*-}        # take number
  name=${name%-*}           # remove number
  new="$number-$name.$ext"  # set new name
  echo mv "$old" "$new"     # test rename
done

echo有効な場合は、最後のエントリを削除してください。

答え4

これは移植可能なsh実装です。

find . -name "*[0-9].mp4" |
    sed "s/\(.*\/\)\(.*\)-\([0-9]*\)\.mp4/'\1\2-\3.mp4' '\1\3-\2.mp4'/" |
    xargs -p -L 1 mv -v

コマンドは非常に簡単です。拡張子の前に1つ以上の数字を含むファイルfindのみを返します。.mp4

このsedコマンドは各ファイル名を一重引用符で囲み、ファイル名をコピーし、2番目のファイル名は相対ファイルパスとファイル名の間の数値部分を移動します'./a/Boil an egg-456707' './a/456707-Boil an egg.mp4'

これにより、現在のファイル名と新しいファイル名の結果リストがxargs実行されるコマンドに渡されますmv -v。このオプションは、一度に1行を処理する-L 1ために必要です。このコマンドからオプションを削除し、使用する必要があるオプションを変更xargできます。-pmv

bashファイルリストを使用して、Ubuntu、Mac OS High Sierra、およびMac OS High Sierraでこの実装をテストし、ファイルをsh別のサブディレクトリに配置し、資格のないファイルを追加しました。bashsh

関連情報