Existem dois problemas principais na resolução deste problema. Você precisa encontrar todos os arquivos com certos sufixos de nome de arquivo, dados por um usuário, e você precisa adicioná-los a um arquivo tar .
O comando find tem uma opção -name que você deseja usar corretamente, mas só pode usar um único padrão de nome de arquivo. Como o usuário do script está nos dando vários sufixos de nome de arquivo, teríamos que usar tantas opções de -name quantas forem sufixos.
Isso significa que temos que construir uma matriz de várias opções -name "PATTERN" , com -o entre elas (significando um "OR" lógico entre elas). Isso seria então usado com find para procurar nomes de arquivos com qualquer um dos sufixos de nomes de arquivos fornecidos.
O seguinte faz isso modificando a matriz $@ :
#!/bin/sh
for suffix do
shift
set -- "$@" -o -name "*.$suffix"
done
shift # remove the very first "-o" from $@
find . -type f \( "$@" \)
Isso modifica a matriz $@ que, desde o início, já contém os sufixos dados na linha de comando. No loop, removemos o elemento frontal de $@ e inserimos nossas palavras no final da matriz.
Se chamar este script como
sh script.sh sh txt c
ele criaria um comando find que seria equivalente a
find . -type f \( -name '*.sh' -o -name '*.txt' -o -name '*.c' \)
Isso encontra todos os arquivos relevantes. Agora só temos que adicioná-los ao arquivo.
Com GNU tar (mas não com, por exemplo, BSD tar ), a ação r nos permite atualizar ou criar um arquivo (o BSD tar apenas atualiza mas não cria um novo arquivo).
backup=./PATH/backup.tar
rm -f "$backup"
find . -type f \( "$@" \) -exec tar -r -v -f "$backup" {} +
Isso criaria o arquivo ./PATH/backup.tar com os arquivos relevantes.
O motivo pelo qual eu não uso tar -c é que quando chamamos tar de find assim, tar pode ser chamado mais de uma vez. Se eu usasse tar -c para criar um novo arquivo, esse arquivo seria truncado sempre que tar fosse chamado (o que pode ser muitas vezes se find encontrar muitos milhares de arquivos). Usando tar -r , apenas continuamos atualizando o arquivo.
Assim, o script completo pode parecer algo assim:
#!/bin/sh
backup=./PATH/backup.tar
if [ "$#" -eq 0 ]; then
echo 'No filename suffixes given' >&2
exit 1
fi
for suffix do
shift
set -- "$@" -o -name "*.$suffix"
done
shift # remove the very first "-o" from $@
rm -f "$backup"
find . -type f \( "$@" \) -exec tar -r -v -f "$backup" {} +
Observe que o uso de citações no script acima é bastante deliberado. Isso tornará possível arquivar arquivos com qualquer nome de arquivo permitido, incluindo nomes que contenham espaços, novas linhas e outros caracteres incomuns.
Relacionados:
Se estiver usando uma implementação find que tenha -print0 , você também pode passar os nomes dos caminhos encontrados para o GNU tar como no script abaixo:
#!/bin/sh
backup=./PATH/backup.tar
if [ "$#" -eq 0 ]; then
echo 'No filename suffixes given' >&2
exit 1
fi
for suffix do
shift
set -- "$@" -o -name "*.$suffix"
done
shift # remove the very first "-o" from $@
find . -type f \( "$@" \) -print0 | tar -c -v -f "$backup" --null -T -
Com -print0 , find produzirá nomes de caminho delimitados por nul que o GNU tar lerá com suas opções --null -T - .
Esse último script como um script bash -específico (usando uma matriz, names para as opções -name ):
#!/bin/bash
backup=./PATH/backup.tar
if [ "$#" -eq 0 ]; then
echo 'No filename suffixes given' >&2
exit 1
fi
names=( -name "*.$1" )
shift
for suffix do
names+=( -o -name "*.$suffix" )
done
find . -type f \( "${names[@]}" \) -print0 | tar -c -v -f "$backup" --null -T -