Как подготовить файлы к rsync в нечувствительной к регистру файловой системе?

Для получения локализованной страницы руководства установите LC_MESSAGES переменная среды локали. Для единственного вызова man:

LC_MESSAGES=ru_RU man man

Если Вы всегда хотите страницы руководства на русском языке, но хотите, чтобы другие команды говорили на английском языке, можно настроить псевдоним в Вашем .bashrc или другой файл инициализации оболочки:

alias man='LC_MESSAGES=ru_RU man'

3
06.11.2013, 23:26
4 ответа

Второй шаг в Вашем конвейере немного повреждается (он искажает обратные косые черты и ведущий и запаздывающий пробел), и сложный способ сделать это. Использовать tr преобразовать в нижний регистр. Вы не должны ограничивать поиск файлами: каталоги могут столкнуться также.

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

Обратите внимание, что это только работает, если имена файлов не содержат новые строки. В соответствии с Linux, переключателем к пустым байтам как разделитель для преодоления новых строк.

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
2
27.01.2020, 21:28
  • 1
    @AntoineLecaille. Это - флаг globbing. –  Gilles 'SO- stop being evil' 07.11.2013, 09:43
  • 2
    @AntoineLecaille, я забыл: Вам нужно setopt extended_glob (как много других полезных globbing функций). комната –  Gilles 'SO- stop being evil' 07.11.2013, 15:38
  • 3
    $ {конфликты [1,-2]} является мертвым кодом. Условие (($ {# $ {(@u) h}} == 1)) является неправильным. Я отлаживаю (и изучаю zsh одновременно).. –  alecail 07.11.2013, 15:49
  • 4
    @AntoineLecaille, который Это, как предполагается, проверяет, существует ли уникальный элемент после преобразования в нижний регистр. А-ч, преобразование в нижний регистр отсутствует! Сделайте это ((${#${(@u)h:l}} == 1)) –  Gilles 'SO- stop being evil' 07.11.2013, 15:55
  • 5
    я все еще не посмотрел, почему условие не работает, потому что я решил свою проблему с моим сценарием. Но существует проблема. –  alecail 08.11.2013, 20:12

Я работаю над решением с помощью awk для дублирующихся имен файлов только, который не сравнивает содержание.

Здесь awk файл dups.awk

#!/usr/bin/awk -f
{
lc=tolower($0);
count[lc] = count[lc]+1;
tab[lc] = tab[lc] "*" $0;}
END {for (t in tab)
  if (count[t]>1) {
   split(tab[t],sp,"*");
   r=1;sep="# ";
   for (fn in sp) 
      if (length(sp[fn])) 
           {
            print  sep "rm '" sp[fn] "'";
            if (r==1) {r=0; sep="  ";}
            }
   print ""; }
}

Я называю его как это:

#!/bin/zsh
find $1 -type f | dups.awk

Существует один дефект: это не будет работать с именами файлов со звездой в нем.

Здесь в действии:

ks% md5sum test/*                               
e342e6ab6ae71954a772409f23390fa4  test/file1
e342e6ab6ae71954a772409f23390fa4  test/File1
e342e6ab6ae71954a772409f23390fa4  test/file2

ks% ./dupsAwk.sh test               
# rm "test/File1"
  rm "test/file1"
0
27.01.2020, 21:28

Вот решение с помощью Perl File::Find вместо того, чтобы пытаться работать вокруг запутанности оболочки:

#!/usr/bin/env perl

use strict;
use warnings;
use File::Find;
use Digest::MD5 qw(md5); # To find duplicates

my %lower_case_files_found;
find(
      sub{
          -f or return; # Skip non-files
          push @{$lower_case_files_found{+lc}},$File::Find::name;
      },
      '.'
);
for my $lower_case_name (sort keys %lower_case_files_found){
    my $number_of_files = scalar @{$lower_case_files_found{$lower_case_name}};
    if($number_of_files > 1){
           my %digests_seen;
           for my $file (@{$lower_case_files_found{$lower_case_name}}){
               open my $fh,'<',$file or die "Failed to open $file: $!\n";
               my $file_content = do {local $/;<$fh>};
               my $digest = md5($file_content);
               push @{$digests_seen{$digest}},$file;
           }
           for my $digest (sort keys %digests_seen){
               my $num_of_files = scalar @{$digests_seen{$digest}};
               if ($num_of_files > 1){
                   print "Duplicates: \n";
                   print "[$_]\n" for @{$digests_seen{$digest}}
               }
           }
    }
}

Это использует сумму MD5 для определения дубликатов файлов и печатает списки простофиль, которых она нашла. В каждое имя файла включают [] помочь Вам визуально определить имена файлов, содержащие новую строку. Я сознательно не добавил код для удаления любых файлов, поскольку этот код полностью не тестируется. Я оставляю его до Вас, чтобы сделать то, что Вы хотите с получающимся списком.

Ожидайте верхнюю память и использование ЦП, если Ваши файлы будут большими в размере: вышеупомянутый сценарий загружает каждый файл в память и выполняет сумму MD5 на ее целом содержании.

0
27.01.2020, 21:28
  • 1
    у меня, оказывается, есть два действительно противных файла: [Cc] hr$ (32) .ttf.Your сценарий не находит их. –  alecail 06.11.2013, 18:24
  • 2
    @AntoineLecaille проверьте обновленный ответ. –  Joseph R. 06.11.2013, 18:54
find . -type f |sort |tee f1 |uniq -i |comm -3 - f1

Даст Вам список файлов, чтобы удалить или проигнорировать, который Вы могли передать по каналу в черный список для rsync

24 часа спустя:

В Ответе на Ваш комментарий "Это непрактично, мне нужны другие, находят", просто передайте результаты по каналу во что-то, что сделает Ваш переименовывать искажение. например, целое решение на одной командной строке, но менее читаемый.

find . -type f |sort |tee f1 |uniq -i |comm -3 - f1|(n=0;while read a ;do  n=$((${n}+1));echo mv ${a} `echo ${a}|tr \[:upper:\] \[:lower:\]`_renamed_${n};done)
0
27.01.2020, 21:28
  • 1
    Обратите внимание, что это предполагает, что файлы, соответствие имен которых нечувствительно к регистру является на самом деле дубликатами, которые не должны иметь место. –  Joseph R. 06.11.2013, 14:34
  • 2
    Это дает Вам список файлов, о которых необходимо будет сделать что-то, если Вы не захотите игнорировать их, Вы могли бы переименовать их. –  X Tian 06.11.2013, 17:08
  • 3
    Это отвечает на Ваш исходный вопрос, если Вы находите, что новые требования просто адаптируют решение, которое я дал. любой путем заключения в кавычки переменных и/или добавления символов к переводить алфавитам. Это не форум. –  X Tian 09.11.2013, 02:18

Теги

Похожие вопросы