Gerar uma lista de arquivos canalizando a saída do comando find para outro comando find?

2

Eu preciso gerar uma lista de arquivos para uso em um script de shell. A lista deve ser todos os arquivos (em um diretório especificado) que estão com hardlink. Eu quero substituir os hardlinks por links simbólicos.

(Obviamente, não consigo excluir o último link. E essa questão está relacionada a esta outra questão que tem uma falha fatal.)

Estou aberto a sugestões sobre como fazer isso. Se você acha que essa pergunta é uma duplicata, certifique-se de que a outra resposta realmente funciona . Ainda não encontrei uma solução de trabalho que atenda a esses requisitos.

  • procura em um diretório que contém potencialmente arquivos com hardlink para manter
  • procura por outros arquivos com link físico a partir de um diretório de nível superior ou raiz do sistema de arquivos
  • os dois diretórios podem ser fornecidos como parâmetros
  • também pode atuar em arquivos de tipos especificados apenas (por exemplo, imagens)

A minha (nova) ideia é canalizar a saída deste find

find "$dir" -type f -links +1

Para este:

find "$topdir" -xdev -samefile <output from other find> -printf '%i:%p\n' | sort --field-separator=:

Se isso funcionar, fornecerei a lista resultante para um loop while semelhante a este (do código original):

last_inode=
while IFS= read -r path_info
do
   inode=${path_info%%:*}
   path=${path_info##*:}
   if [[ $last_inode != $inode ]]; then
       printf "$inode\n"
       last_inode=$inode
       path_to_keep=$path
   else
       rm -- "$path"
       ln -s -- "$path_to_keep" "$path"
   fi
done

Eu também posso adicionar um parâmetro como -iname "*.jpg" ao (primeiro) comando find para atuar somente em arquivos JPEG. (Eu também estou aberto a sugestões melhores aqui.)

    
por MountainX 30.03.2012 / 02:58

1 resposta

1

Aqui está uma solução que funciona. Eu testei bastante extensivamente. No entanto, saúdo as melhores respostas. Prefiro selecionar a resposta de outra pessoa que a minha (o que diz algo sobre minha confiança nas minhas habilidades de script bash).

find "$dir" -type f -links +1 -exec find "$topdir" -xdev -samefile '{}' -printf '%i:%p\n' \; | sort --field-separator=:

Aqui está a solução completa, estendendo a pergunta vinculada (supondo que funcione):

#!/bin/bash
set -o nounset
topdir='/'
dir='/MotherBoards/Tyan S2720 Thunder i7500/IntelNetworkAdapterDrivers/Setup/'

echo "starting..."

# For each path which has multiple links
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# (except ones containing newline)
last_inode=
while IFS= read -r path_info
do
   inode=${path_info%%:*}
   path=${path_info##*:}
   if [[ $last_inode != $inode ]]; then
       printf "$inode\n"
       last_inode=$inode
       path_to_keep=$path
   else
       printf "$inode\tln -s\t'$path_to_keep'\t'$path'\n"
       rm -- "$path"
       ln -s -- "$path_to_keep" "$path"
   fi
done < <( find "$dir" -type f -links +1 -exec find "$topdir" -xdev -samefile '{}' -printf '%i:%p\n' \; | sort --field-separator=: )

# Warn about any excluded files
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
buf=$( find "$dir" -type f -links +1 -wholename '*
*' )
if [[ $buf != '' ]]; then
    echo 'Some files not processed because their paths contained newline(s):'$'\n'"$buf"
fi

echo "finished"
exit 0
    
por 30.03.2012 / 04:04