大文字と小文字を区別しないファイルシステムでrsync用のファイルをどのように準備しますか?

大文字と小文字を区別しないファイルシステムでrsync用のファイルをどのように準備しますか?

HFS +ファイルシステムから大量のファイルを転送しています。

このファイルは現在ext2パーティションにあります。

ターゲットパーティション(HFS +)が大文字と小文字を区別しないため、競合が発生します。

重複したファイル名を持つ小文字のファイルを識別し、実際に重複している場合は削除したいと思います。

また、すべてを小文字に変換すると、フォルダ名が重複するという事実も発見しました。デフォルトでは、これらのハードドライブには長年ソートされていないデータが含まれており、フォルダ名にも問題があります。

これは合理的に見えますか?

find . -type f | while read f; do echo $f:l; done | sort | uniq -d 

$f:l小文字に変換するのはZSHです。

今、重複した各ファイルのインスタンスを1つだけ維持したいと思います。これを効果的に行う方法は?

重複したファイルを探したくありません。コンテンツ、同じ小文字のファイル名がない限り。後で重複した内容を扱います。

ベストアンサー1

パイプラインの2番目のステップはわずかに損傷し(バックスラッシュと先行スペースと末尾のスペースを分離)、複雑なアプローチです。tr小文字に変換するために使用されます。検索をファイルに制限しないでください。ディレクトリでも競合が発生する可能性があります。

find . | tr '[:upper:]' '[:lower:]' | LC_ALL=C sort | LC_ALL=C uniq -d

これは、ファイル名に改行文字が含まれていない場合にのみ機能します。 Linuxでは、改行を処理するための区切り文字でNULLバイトに切り替えます。

find . -print0 | tr '[:upper:]' '[:lower:]' | LC_ALL=C sort -z | LC_ALL=C uniq -dz

これはファイル名の小文字のバージョンを印刷しますが、これは実際にファイルに対して特定の操作を実行するのに役立ちません。

zshを使用している場合は忘れてくださいfind。必要なものはすべてzshに組み込まれています。

setopt extended_glob
for x in **/*; do
  conflicts=($x:h/(#i)$x:t)
  if (($#conflicts > 1)); then
    ## Are all the files identical regular files?
    h=()
    for c in $conflicts; do 
      if [[ -f $c ]]; then
        h+=(${$(md5sum <$c)%% *})
      else
        h=(not regular)
        break
      fi
    done
    if (( ${#${(@u)h}} == 1 )); then
      # Identical regular files, keep only one
      rm -- ${conflicts[1,-2]}
    else
      echo >&2 "Conflicting files:"
      printf >&2 '    %s\n' $conflicts
    fi
  fi
done

おすすめ記事