text processing - Como classificar a saída do find que possui nomes de arquivos duplicados de um diretório diferente?

1

Eu quero classificar esta saída do comando find sem nomes de arquivos duplicados em qualquer diretório.

find /path/to/first_directory/* /path/to/second_directory/* /path/to/third_directory/* -mtime -1 -name "filename_pattern*"

exemplo de saída:

/path/to/first_directory/sample_file1_2017Dec25.dat
/path/to/first_directory/sample_file2_2017Nov01.dat
/path/to/first_directory/sample_file3_2017Oct08.dat
/path/to/first_directory/archive/sample_file1_2017Dec25.dat.Z
/path/to/first_directory/archive/sample_file2_2017Nov01.dat.Z
/path/to/second_directory/sample_file4_2017Sep11.dat
/path/to/second_directory/sample_file5_2017Oct05.dat
/path/to/third_directory/sample_file1_2017Dec25.dat
/path/to/third_directory/sample_file2_2017Nov01.dat
/path/to/third_directory/sample_file3_2017Oct08.dat
/path/to/third_directory/sample_file4_2017Sep11.dat
/path/to/third_directory/sample_file5_2017Oct05.dat
/path/to/third_directory/sample_file6_2017July04.dat
/path/to/third_directory/sample_file6_2017June12.dat
/path/to/third_directory/sample_file7_2017May01.dat

Na saída, você pode ver que há nomes de arquivos duplicados em /first_directory/ e /first_directory/archive/ e também todos os arquivos de /first_directory/* e /second_directory/* também estão dentro de /third_directory/* . Isso significa que /third_directory/* é o diretório de arquivamento de todos os arquivos encontrados em /first_directory/* e /second_directory/* , mas também há arquivos que só podem ser encontrados em /third_directory/* (verifique sample_file6 e sample_file7 )

Tudo o que desejo imprimir são os arquivos originados de /first_directory/ to /first_directory/archive/ to /second_directory/ to /third_directory/ nesta ordem sem serem duplicados e também classificados por suas datas.

Saída desejada:

/path/to/first_directory/sample_file1_2017Dec25.dat
/path/to/first_directory/sample_file2_2017Nov01.dat
/path/to/first_directory/sample_file3_2017Oct08.dat
/path/to/second_directory/sample_file4_2017Sep11.dat
/path/to/second_directory/sample_file5_2017Oct05.dat
/path/to/third_directory/sample_file6_2017July04.dat
/path/to/third_directory/sample_file6_2017June12.dat
/path/to/third_directory/sample_file7_2017May01.dat
    
por WashichawbachaW 06.12.2017 / 04:02

1 resposta

1

Se a saída do seu comando find for salva em um arquivo chamado filelist , tente:

$ awk -F/ '{f=$NF; sub(/\.Z$/,"",f)} !a[f]++' filelist
/path/to/first_directory/sample_file1_2017Dec25.dat
/path/to/first_directory/sample_file2_2017Nov01.dat
/path/to/first_directory/sample_file3_2017Oct08.dat
/path/to/second_directory/sample_file4_2017Sep11.dat
/path/to/second_directory/sample_file5_2017Oct05.dat
/path/to/third_directory/sample_file6_2017July04.dat
/path/to/third_directory/sample_file6_2017June12.dat
/path/to/third_directory/sample_file7_2017May01.dat

Se você quiser fazer a mesma coisa sem criar o arquivo:

find /path/to/first_directory/* /path/to/second_directory/* /path/to/third_directory/* -mtime -1 -name "filename_pattern*" | awk -F/ '{f=$NF; sub(/\.Z$/,"",f)} !a[f]++'

Ou você prefere distribuir o comando por várias linhas, use:

find /path/to/first_directory/* /path/to/second_directory/* \
  /path/to/third_directory/* -mtime -1 -name "filename_pattern*" |
    awk -F/ '{f=$NF; sub(/\.Z$/,"",f)} !a[f]++'

onde adicionamos \ ao final da primeira linha porque são os caracteres de continuação de linha do bash. Como a segunda linha termina com | , ela não exige um caractere de continuação de linha.

Como funciona

Primeiro, é importante que os diretórios sejam listados no comando find em sua ordem de prioridade. Eu vejo que você já fez isso.

  1. -F/

    Isso informa ao awk para usar / como o separador de campo. Isso significa que o nome do arquivo será o último campo, $NF .

  2. f=$NF; sub(/\.Z$/,"",f)

    Isso atribui o nome do arquivo à variável f e, em seguida, remove o% final.Z de f , se houver.

  3. !a[f]++'

    Se f não foi visto antes, imprima esta linha.

Atualização 1: remoção de outras extensões

De acordo com os comentários, .Z não é a única extensão que precisa ser removida.  Pode haver outras extensões .dat.edi e .dat.bak que devem ser substituídas simplesmente por .dat . Nesse caso:

awk -F/ '{f=$NF; sub(/\.dat.*/,".dat",f)} !a[f]++' filelist

Atualização 2: exibindo arquivos classificados por timestamp:

awk -F/ '{f=$NF; sub(/\.dat.*/,".dat",f)} !a[f]++' filelist | xargs -d'\n' -r ls -t
    
por 06.12.2017 / 04:17