POSIX 移植性とともに、すべてのタイプの文字を使用して多数のファイル名を変更します。

POSIX 移植性とともに、すべてのタイプの文字を使用して多数のファイル名を変更します。

時にはディレクトリ内のすべてのファイルの名前を変更する必要があります(名前変更規則は後で説明します)。ここで、ファイル名は常に「filenamename.extension」形式です(拡張子は常に存在し、変更されます)。名前には、[:graph:]クラスのスペースと文字を含めることができます。最初の質問は、* NIXシステム(特にLinux、BSD、およびAIXなどの他のシステム)間で完全に移植可能でなければならないことです。 2番目の質問は[:graph:]クラスについてです。ファイル名は次のとおりです。

cat.txt
dog_and_cat.txt
Where is the cat?.png
my.cat.is.cute.txt.js.html
;;; ;;; ;;;.......321
áéúő _[a lot of whitespaces]_ óü^^^^^ö.jpg

これを処理してforループに入れることが難しいことが簡単にわかります。例えば、

for i in *; do something; done

特に、さまざまなオペレーティングシステムでは、空白と奇妙な文字が常に好まれるわけではありません。

名前変更規則は、すべてのファイルの名前をmd5sumなどの特定の$FOOBAR.$EXTENSION形式のハッシュに変更することです。$FOOBARforループ内には次のような行があります。

mv $FILE $(md5sum $FILE | sed 's/\ \ .\+//');

ファイルを独自の md5sum に移動しますが、拡張子は消えます。拡張機能を維持したい。ほぼ常にフォーマットです.[a-zA-Z0-9]{1,3}。時には.tar.gz同様の拡張を維持する必要があるかもしれません(もちろん変数に追加することができますMYEXTENSIONS='tar.gz tar.bz2 foo.bar')。

私の直感では、この問題はよくパラメータ化された基本的なUNIX /シェルコマンドで解決できると言っていますが、今は非常に難しいです。答えからたくさん学ぶことができると確信しています。私が魔法の言葉を言ったことを知っています。移植性ただし、言語を指定する必要がある場合、好ましい解決策はbashです。

ベストアンサー1

実際にaで始まるファイル名がワイルドカード一致から除外されるfor i in *; do something; doneことを除いて、すべてのファイル名は正しく処理されます。.すべてのファイル(.および除外..)を移植可能に一致させるには、一致しない* .[!.]* ..?*パターンがそのまま残り、存在しないファイルを一致させてスキップします。

$i問題が発生した場合は、後で引用符が正しくないためです。変数置換とコマンド置換は常に二重引用符で囲みます"$foo""$(cmd)"フィールド分割とワイルドカードの発生を計画しない限り。

ファイル名を外部コマンドに渡す必要がある場合(ここでは必要ありません)、必ずしも文字通りecho "$foo"印刷$fooされるわけではありません。一部のシェルはバックスラッシュ拡張を実行し、$fooで始まるいくつかの値は-オプションとして扱われます。文字列を正確に印刷する安全でPOSIX互換の方法は次のとおりです。

printf '%s' "$foo"

またはprintf '%s\n' "$foo"最後に改行文字を追加してください。注目すべきもう1つの点は、コマンド置換が末尾の改行を削除することです。改行を維持する必要がある場合は、可能な1つの方法は、改行以外の文字をデータに追加し、変換時にその文字が保持されることを確認してから、最後にその文字を切り捨てることです。たとえば、

mangled_file_name="$(printf '%sa' "$file_name" | tr -sc '[:alnum:]-+_.' '[_*]')"
mangled_file_name="${mangled_file_name%a}"

ファイルのmd5sumを抽出するには、出力にファイル名を含めないでくださいmd5sum。これにより削除が困難になります。データをmd5sum標準入力に渡します。

このmd5sumコマンドは POSIX にはありません。一部のUNIXバリアントにはこの機能があるか、md5まったくありません。cksumPOSIXですが、競合が発生しやすいです。

バラよりファイル名の拡張子を取得します。ファイル拡張子を取得する方法。

みんなでまとめてみましょう(テストされていません)。ここにあるすべての機能はPOSIXシェルで動作しますが、いくつかのbash機能を提供しますが、あまり多くはありません。

for old_name in * .[!.]* ..?*; do
  if ! [ -e "$old_name" ]; then continue; fi
  hash=$(md5sum <"$old_name")
  case "$old_name" in
    *.*.gz|*.*.bz2)                   # double extension
      ext=".${old_name##*.}"
      tmp="${old_name%.*}"
      ext=".${old_name##*.}$ext";;
    ?*.*) ext=".${old_name##*.}";;    # simple extension
    *) ext=;;                         # no extension
  esac
  mv -- "$old_name" "$hash$ext"
done

指定された名前の宛先ファイルがすでに存在する場合は考慮されません。特に名前が採用したルールに似ていますが、チェックサム部分がファイルの内容と一致しませんが、同じ拡張子を持つ他のファイルの内容が相対的な事前編成順序に依存する既存のファイルがある場合はどうなりますか?ファイル名。

おすすめ記事