特定のファイル形式(.mkv、.mp4、.avi)に対してのみ、ディレクトリ内でアンダースコアの検索と置換を実行しようとしています。以下は私が使用しているコードです(Mac OS X 10.9を使用しています)。
find . \( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' \) -print0 |
xargs -0 sed -i '' -e 's/\./_/g'
私は2つの解決策を読んだが、どちらも機能しません。
まず、~/.bash_profileに以下を追加しました。
export LC_CTYPE=C
export LANG=C
これで同じエラーが発生し、次のことを試しました。
LC_ALL=C sed ...
動作しません。次のエラーが発生します。
xargs: LC_ALL=C: No such file or directory
他に提案がありますか?私はシェルに初めて触れました。
編集する:これが私が達成したいものです:
ディレクトリを繰り返し、ファイル名の下線をドットに変更しようとします。
例:
random_movie.mp4はrandom.movie.mp4でなければなりません。
ベストアンサー1
ここで使用する必要があります-exec
:
find . \( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' \) \
-exec sh -cf 'IFS=._
for f do d=${f%/*} f=${f##*/}
[ -n "${f##*_*}" ] && continue
set -- $f
printf "%s\n" "mv \\" "$d/$f \\" "$d/$*"
done' find.rename.shc {} +
作成したとおり、これは実行時に実行するコマンドのみを印刷します。たとえば、私のディレクトリで上記のコマンドを実行すると、次の.../media/Videos
一部が印刷されます。
mv \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure_Time.s05e37.The_Box_Prince.mp4 \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure.Time.s05e37.The.Box.Prince.mp4
mv \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure_Time.s05e38.Red_Starved.mp4 \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure.Time.s05e38.Red.Starved.mp4
これを達成するには、以下を変更する必要があります。
...
set -- $f
printf "%s\n" "mv \\" "$d/$f \\" "$d/$*"
...
...ただ...
...
set -- $f; mv "$d/$f" "$d/$*"
...
通常、パイプを介してファイル名などを渡すことは避けてください。これは、ファイル名の先頭と末尾の区切り文字が失われるためです。これはもはやパラメータではなくバイトシーケンスになります。この-exec
オプションを使用するfind
と、実行中のプロセスの子プロセスでこれらの区切り文字を保持できますfind
。これは+
次のように機能しますxargs
。特定ARGMAX
の状況を回避するために必要な場合にのみ、指定されたサブプロセスを実行します。
このsed
問題に関しては、次のことを試すことができます。
LC_ALL=C xargs sed ...
少なくともxargs
、環境変数宣言がパラメータとして解釈されるのを防ぐ必要があります。ただし、ファイル名の編集には役立ちません。
最後に述べた問題は、通常、パターン空間に現れる不完全なマルチバイトシーケンスが原因で発生します。 POSIX 仕様が.
一致しません。部分文字 - したがって、.*
その文脈で意味を失います。ロケールを強制的に適用するとこの問題は解決されますが、GNUコマンドをC
使用して予約/パターンスペースを消去する別のオプションがあります。sed
z