3 votes

Ajouter le nom du fichier au fichier txt s'il n'est pas à zéro octet

J'aimerais ajouter les fichiers qui répondent à un ensemble de conditions à un fichier txt pour faciliter le transfert ultérieur, je le fais avec :

ls -1 > AllFilesPresent.txt

value=$(<AllFilesPresent.txt)

rm AllFilesPresent.txt

for val in $value; do
  case $val in
    (Result*.RData) echo "$val" >> CompletedJobs.txt ;;
  esac
done

J'ai rencontré une situation où certains fichiers sont corrompus et apparaissent comme des fichiers de zéro octet, que je peux trouver manuellement :

find . -size 0 -maxdepth 1

Comment puis-je inclure l'ajustement de ma boucle pour rejeter les fichiers qui sont à zéro octet ?

3voto

pjh Points 1139

Le code

ls -1 > AllFilesPresent.txt
value=$(<AllFilesPresent.txt)
rm AllFilesPresent.txt
for val in $value; do

a une fonctionnalité essentiellement identique à celle de

for val in $(ls -1); do

Cela ne fonctionne pas en général. Il ne fonctionne pas si les noms de fichiers contiennent des espaces ou des caractères globaux, au moins. Voir Pièges de Bash #1 (for f in $(ls *.mp3)) . En outre, l'utilisation des données de sortie de la ls dans les programmes. Il ne convient qu'à une utilisation interactive. Voir aussi Pourquoi ne pas analyser la sortie de ls(1) .

Il existe une alternative correcte, totalement sûre, beaucoup plus courte et rapide :

for val in *; do

La solution complète à votre question est la suivante :

shopt -s nullglob
for file in Result*.RData; do
    [[ -f $file && -s $file ]] && printf '%s\n' "$file"
done >CompletedJobs.txt
  • shopt -s nullglob empêche les motifs globaux de se transformer en (ce qui équivaut à) des déchets s'ils ne correspondent à aucun fichier.
  • J'ai remplacé val avec le plus significatif (pour moi en tout cas) file .
  • En Result*.RData fait en sorte que la boucle ne traite que les fichiers qui correspondent à ce motif.
  • J'ai ajouté un -f $file pour éviter de traiter tout ce qui n'est pas un fichier (répertoires, fifos, ...) et qui pourrait traîner dans les parages. Il autorise toujours les liens symboliques vers les fichiers. Il se peut que vous ne souhaitiez pas cela. Vous pouvez ajouter un ! -L $file && au début de l'expression du test si vous souhaitez exclure les liens symboliques.
  • J'ai remplacé echo "$val" con printf '%s\n' "$val" parce que le code original ne fonctionne pas en général. Voir la réponse acceptée, et excellente, à Pourquoi printf est-il préférable à echo ? .
  • J'ai déplacé la redirection vers CompletedJobs.txt à l'extérieur de la boucle, comme l'a suggéré @CharlesDuffy dans une commentaire .
  • Notez que ce code ne fonctionnera pas si l'un des fichiers a des lignes nouvelles dans son nom (par exemple, créer un fichier avec echo data > $'Result\n1.RData' ). C'est très rare, mais possible. La seule façon de stocker en toute sécurité des noms de fichiers généraux sans guillemets dans des fichiers est de les séparer par des caractères ASCII NUL (qui ne peuvent pas apparaître dans les noms de fichiers). Pour ce faire, remplacez le caractère printf ... con printf '%s\0' "$file" . Cela signifie que CompletedJobs.txt n'est plus un fichier texte. Il faudrait également modifier tous les outils qui lisent le fichier.

Vous pouvez également le faire avec find :

find . -maxdepth 1 -type f -name 'Result*.RData' -not -size 0 -printf '%P\n' >CompletedJobs.txt
  • En %P avec le format -printf supprime le premier ./ à partir des sorties, ce qui permet d'obtenir Result2.RData au lieu de ./Result2.RData (qui find s'imprimerait par défaut, ou avec l'option -print ).
  • Remplacer \n con \0 pour que la sortie soit sûre pour tout nom de fichier possible.

-1voto

Rakesh Gupta Points 434

-s fichier Vrai si le fichier existe et a une taille supérieure à zéro.

ls -1 > AllFilesPresent.txt
value=$(<AllFilesPresent.txt)
rm AllFilesPresent.txt
for val in $value; do
  if [[ -s "${val}" ]]; then
    case $val in
      (Result*.RData) echo "$val" >> CompletedJobs.txt ;;
    esac
  fi
done

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X