Como fixar certos arquivos ao usar ordenação?

3

Normalmente, sou mais criativo com comandos e pipes Unix, mas não hoje.

Então, o que eu tenho é isso:

collage.jpg
DCIM001.jpg
DCIM002.jpg

ou isto:

001.jpg
002.jpg
boston-collage.jpg

ou às vezes

panama-collage.jpg
DCIM001.jpg
DCIM002.jpg

Agora eu uso esse comando, que classifica as imagens corretamente.

find "Image Folder" -print0 | sort -z | tar cv --no-recursion --null -T -

Mas eu gostaria de corrigir arquivos com * collage. * como os primeiros arquivos dos resultados de classificação para adicioná-los primeiro ao arquivo tar que estou criando nessa lista. Alguma idéia?

    
por Christian P 06.03.2016 / 15:33

2 respostas

2

Se o objetivo final é colocar os arquivos no arquivo na ordem desejada, uma solução simples é criar um arquivo com os arquivos para classificar primeiro e depois adicionar os arquivos para classificar por último no arquivo existente. Isso pode ser generalizado para mais de dois segmentos de classificação. Isso requer a criação de um arquivo, você não pode acrescentar a um arquivo em um pipeline.

tar cf foo.tar /images/*collage.*
find /images ! -name '*collage.*' -print0 | sort -z | tar rf foo.tar --null -T -

Se você quiser executar uma classificação personalizada com apenas utilitários básicos, um método possível é adicionar um prefixo à linha que indica o grupo do qual o item faz parte. Organize para que as tags de prefixo sejam classificadas na ordem em que você deseja que os grupos sejam classificados e retire esses prefixos posteriormente.

find /images -print0 |
sed -z -e 's/.*collage\./1&/' -e 't' -e 's/^/2/' |
sort -z |
sed -z 's/^.//' |
tar …

Outra abordagem seria fazer a classificação em outro idioma, como Perl, Python ou Ruby, onde você pode expressar uma classificação personalizada. Se você fizer isso, poderá fazer a coleta de nomes de arquivos e até mesmo a produção do arquivo nesse idioma. Aqui está um exemplo de Perl que apenas faz a classificação:

perl -e '$,=$\="
perl -e '$,=$\="
perl -e '$,=$\="
tar cf foo.tar /images/*collage.*
find /images ! -name '*collage.*' -print0 | sort -z | tar rf foo.tar --null -T -
"; print map {substr($_,1)} sort map {$_ = (/collage\./ ? "1" : "2") . $_} glob("/images/*")' /images/* | tar …
"; print map {substr($_,1)} sort map {$_ = (/collage\./ ? "1" : "2") . $_} @ARGV' /images/* | tar …
"; print sort { $a =~ /collage\./ ? $b =~ /collage\./ ? $a cmp $b : 1 : $b =~ /collage\./ ? -1 : $a cmp $b } @ARGV' /images/* | tar …

E outro exemplo que faz a classificação por meio de uma reescrita temporária (é chamada de "transformação Schwarztian" na comunidade Perl):

find /images -print0 |
sed -z -e 's/.*collage\./1&/' -e 't' -e 's/^/2/' |
sort -z |
sed -z 's/^.//' |
tar …

Ambos os exemplos falharão se o comprimento combinado dos nomes dos arquivos exceder o limite de comprimento da linha de comando. Para evitar isso, deixe o Perl gerar os nomes dos arquivos.

perl -e '$,=$\="
perl -e '$,=$\="
perl -e '$,=$\="%pre%"; print
    map {substr($_,1)}
    sort
    map {$_ = (/collage\./ ? "1" : "2") . $_}
    glob("/images/*")' /images/* | tar …
"; print map {substr($_,1)} sort map {$_ = (/collage\./ ? "1" : "2") . $_} @ARGV' /images/* | tar …
"; print sort { $a =~ /collage\./ ? $b =~ /collage\./ ? $a cmp $b : 1 : $b =~ /collage\./ ? -1 : $a cmp $b } @ARGV' /images/* | tar …

Se você precisar gerar nomes de arquivos recursivamente ou aplicar alguma filtragem, use Arquivo :: Localizar . Se você quiser gerar o arquivo em Perl, você pode usar o Archive :: Tar .

    
por 06.03.2016 / 18:33
0

Aqui está minha sugestão, usando um arquivo temporário:

tmpdir=$(mktemp)
find "Image Folder" -print0  > $tmpdir/temp
{ grep -z collage $tempdir/temp | sort -z; 
  grep -z -v collage $tempdir/tmp | sort -z; } | \
  tar cv --no-recursion --null -T -
rm -rf $tmpdir

Você poderia usar algo mais simples para o arquivo temporário, desde que não o coloque dentro da "Pasta de Imagem".

A ideia básica por trás dessa solução é salvar os resultados de find em um arquivo temporário para que possamos executar dois grep s, classificando cada resultado de grep individualmente antes de combiná-los no canal para tar .

    
por 06.03.2016 / 18:32