Como listar arquivos de backup faltando arquivos reais correspondentes?

2

Eu acidentalmente excluí alguns arquivos espalhados pelo meu diretório pessoal, mas não sei exatamente quais foram removidos. Como posso obter uma lista de todos os arquivos de backup sem o arquivo correspondente? (equivalentemente, arquivos tendo nomes terminando com um til, sem haver outro arquivo no mesmo diretório com o mesmo nome sem o til seguinte?)

Eu tentei algumas coisas até agora; embora eu não me lembre das bandeiras exatas, era algo como:

grep -Rlv '(.*)\n\1~|.*(?!~)'

Isso não funcionou e nem o fez:

ls -R | grep -v '(.*)\n\1~|.*(?!~)'

Como posso encontrar esses arquivos?

    
por AJMansfield 11.03.2014 / 02:14

3 respostas

4

Basta encontrar todos os arquivos com um til, remover o til e procurar pelo "original":

find . -name '*~' -print0 | while IFS= read -r -d $'
find . -name '*~' -print0 | while IFS= read -r -d $'%pre%' file; do 
  [ -e "${file%\~}" ] ||  echo cp "$file" "${file%\~}"; done 
done 
' file; do [ -e "${file%\~}" ] || echo cp "$file" "${file%\~}"; done done

Explicação:

  • find ~/ -name '*~' -print0 : encontre todos os arquivos em $HOME que terminam em um til e imprima-os com o caractere nulo ( while IFS= read -r -d $'find' file; ). O último é necessário para lidar com nomes de arquivos estranhos que contenham novas linhas, etc.

  • IFS= : leia cada arquivo encontrado por -r em $ file '.

    • -d $'"${file%\~}"' : turnos da divisão automática do bash no espaço em branco
    • [ -e "${file%\~}" ] || echo 'cp '$file' '${file%\~}" : trate as barras invertidas literalmente (não como caracteres de escape)
    • echo : define o delimitador de campo de entrada para o caractere nulo.
  • %code% : remove o til, consulte aqui
  • %code% : o eco será executado somente se o nome do arquivo (sans til) não existir. Para realmente copiar os arquivos, basta remover o %code% .
por 11.03.2014 / 05:23
2

No zsh, você pode usar um qualificador de glob para filtrar correspondências. O modificador e permite que você especifique um código arbitrário; é mais fácil na análise escrever uma função e chamá-la com o modificador + .

zsh -c 'deleted () { ! [ -e ${REPLY%\~} ] }; ls -ld **/*~(+deleted)'

Se o zsh não estiver disponível, você poderá usar o find.

find ~ -name '*~' -type f -exec sh -c '[ -e "${0%\~}" ] && ls -ld "$0"' \;

ou mais rápido:

find ~ -name '*~' -type f -exec sh -c 'for x; do [ -e "${x%\~}" ] && ls -ld "$x"' _ {} +
    
por 12.03.2014 / 01:15
1

Um método alternativo para usar o find. Armazene em cache ambas as listas de arquivos (removendo "~") e diferencie os dois pipes nomeados anônimos que armazenam cada conjunto.

diff <(ls -R *[^~] | xargs -n 1 readlink -f)  <(ls -R *[~] | xargs -n 1 readlink -f | sed 's/~$//')
    
por 11.03.2014 / 18:58