Filtra nomes de arquivos duplicados com tar

3

Estou usando o tar assim,

tar -cjpvf a.tar "$pattern1" "$pattern2"

O problema é que pattern1 e pattern2 às vezes correspondem ao mesmo arquivo, mas o tar parece não filtrar essas duplicatas.

Por exemplo, o exemplo a seguir adiciona duas entradas duplicadas no archive

%> tar -cjpvf a.tar /etc/passwd /etc/passwd
%> tar -xvf a.tar
etc/passwd
etc/passwd

Como posso filtrá-los?

    
por daisy 13.03.2017 / 01:38

3 respostas

3

Se pattern1 e pattern2 forem padrões de curingas de shell, você poderá usar um padrão or.

tar -cjpvf a.tar @($pattern1|$pattern2)

Isso requer ksh, bash ou zsh. No bash, você precisa executar shopt -s extglob primeiro para ativar a sintaxe do padrão @(…) . Em zsh, você precisa executar setopt ksh_glob first (e também dizer ao zsh que as variáveis contêm padrões em vez de strings, portanto @($~pattern1|$~pattern2) ) ou usar a sintaxe nativa ($~pattern1|$~pattern2) .

    
por 14.03.2017 / 02:50
1

Se você se sentir confortável analisando a saída de ls (e assumindo aqui que nenhum dos nomes de arquivo contém caracteres de $IFS ou caracteres curinga ou inicie com - ):

tar -cjpvf a.tar $(ls -d1 <pattern1> <pattern2> | sort | uniq)

ou

tar -cjpvf a.tar $(ls -d1 <pattern1> <pattern2> | sort -u)

Se você não se sentir confortável em analisar a saída de ls , a abordagem correta é usar find (assumindo aqui o GNU tar ou compatível):

find -maxdepth 1 \( -name <pattern1> -o -name <pattern2> \) -print0 \
 | xargs -0 tar -cjpvf a.tar

(supondo que a lista de arquivos seja pequena o suficiente para que apenas uma invocação de tar seja executada. Observe também que find não omite arquivos ocultos por padrão).

    
por 13.03.2017 / 01:50
0

Se o pedido é importante. Por exemplo, se você deseja arquivar foo* e *.txt arquivos e deseja que os arquivos foo* apareçam primeiro no arquivamento (mas foo.txt não será incluído duas vezes). IOW, receba foo.a foo.b foo.txt foo.z a.txt b.txt z.txt nessa ordem:

com zsh :

files=(./foo*(N) ./*.txt(N))
(($#files)) && tar jcf file.tar.bz2 ${(u)files}

com tcsh :

set -f files = (./foo* ./*.txt) && tar jcf file.tar.gz2 $files:q

Se você deseja garantir que *.txt seja o último ( foo.a foo.b foo.z a.txt b.txt foo.txt z.txt nessa ordem):

com zsh :

files=(./foo*(N) ./*.txt(N))
(($#files)) && tar jcf file.tar.bz2 ${(uOa)${(Oa)files}}

( Oa sendo um sinalizador de expansão de parâmetro que reverte a ordem da matriz)

com tcsh :

set -l files = (./foo* ./*.txt) && tar jcf file.tar.gz2 $files:q
    
por 14.03.2017 / 09:10