Unix Supprimer récursivement des fichiers et des dossiers

Je travaille donc sur un programme qui supprime les fichiers et les dossiers de manière récursive. Pour une raison quelconque, je suis coincé dans une boucle sans fin. Veuillez indiquer où je me trompe.

for file in $1 do if [ -f $file ] #If it is a file just delete it then echo "delete $file" elif [ -d $file ] #if it is a folder then #look inside and see if it is empty or not if [ "$(ls -A $file)" ] then recursive $file #recursively call else #if the folder is empty just delete it echo "delete $file" fi fi done 

Tu as

 for file in $1 

 recursive $file #recursively call 

Cela se transforme effectivement en répétition

 for file in $file 

C’est-à-dire qu’il continue à répéter pour la même première entrée de répertoire. Vous devez repenser l’ensemble de la fonction, soit passer des parameters différents en appel récursif, soit ne pas utiliser plus $1 . Le plus simple peut être de changer le for (non testé):

 for file in "$1/*" "$1/.*" 

Ajoutez également un test pour le cas où $file est . ou .. , ou supprimez la partie $file/.* de mon for .


A propos du débogage des scripts bash, il est souvent utile de suivre deux options de set , vous pouvez par exemple les append au début de votre script.

 set -x # print every final command line when it is executed set +x # turn -x off set -v # print script lines as they are read set +v # turn -v off 

Pour plus d’informations à ce sujet, consultez cette question .

Si je comprends ce que vous essayez d’atteindre, je pense que vous feriez mieux d’utiliser la commande find au lieu de lancer votre propre script shell.

Par exemple, la commande suivante devrait supprimer “juste les fichiers” nommés foo.txt partir du répertoire actuel et afficher la liste des fichiers à supprimer.

 find . -name foo.txt -type f -exec rm -v {} \; 

Vous pouvez man find des informations sur l’utilisation de cet outil, mais les options sont essentiellement les suivantes:

trouver le chemin [ chemin …] [ expression ]

chemin est un ou plusieurs répertoires de démarrage pour votre recherche récursive, et expression est une liste de conditions ou d’actions à effectuer.

Dans l’exemple ci-dessus, nous avons deux conditions évidentes: -name foo.txt indique le nom du fichier et -type f indique qu’il s’agit d’un fichier normal. La troisième option de l’expression exécute une ligne de commande terminée par un point-virgule échappé, remplaçant {} par le nom de chaque fichier trouvé.

De même, lors du traitement de plusieurs noms de fichiers, faites attention à ne pas parsingr la sortie de ls . Pour plus de détails, lisez ParsingLs sur le wiki de Greg .

Enfin, si vous essayez de créer un script qui supprime plusieurs noms de fichiers, vous pouvez choisir quelque chose comme ceci:

 #!/bin/sh for file in $@; do find . -type f -name "$file" -exec rm -v {} \; done 

Notez que cela fonctionnera également avec des shells POSIX plus simples, il ne nécessite pas de bash.

Donc je l’ai un peu réécrit. Le code n’est pas aussi efficace mais il fait le travail.

 recursive() { # create a file touch $HOME/temp_file #create a file tree -fi $1 > $HOME/temp_file #tree it up and pump it in the file touch $HOME/temp_file tree -fid $1 > $HOME/temp_file #tree it up and pump it in the file count=$(wc -l $HOME/temp_file | cut -d " " -f1) #loop thru the file that contains only directory for ((i=1;i<=$[$count-2];i++)) do args=$(sed -n $i"p" $HOME/temp_file) #grab line by line if [ -d $args ] #if it is a folder then if recurse_down $args # if recurse down interactive flag is set then if [ "$(ls -A $args)" ] #if dir is not empty then touch $HOME/temp_file2 #store only file name in another file this time ls $args | grep -v ^d > $HOME/temp_file2 count2=$(wc -l $HOME/temp_file2 | cut -d " " -f1) for ((z=1;z<=$count2;z++)) do file=$(sed -n $z"p" $HOME/temp_file2) echo "deleting $file" #call delete function and pass in filename # and the path of it delete $file $args done else echo "Empty dir. Just delete it" delete $args fi else exit fi fi done } delete() { # $2 for path and $1 for filename echo "1 is $1" echo "2 is $2" File=$2/$1 echo "Fileeeeeeee is $File" #echo "node is $node" node=$(stat -c%i $File) #get inode number of the file opFile="$recycleBin"/$(basename "$File")"_$node" #append it echo "opFile is $opFile" no_basename=$(basename "$File") #get basename # it will be like f8_1287540:/home/waiyan.hein/bin/d9/d1/f8 echo "${no_basename}_$node:`pwd`/$File" >> $HOME/.restore.info #now move the file into destination folder mv $File $opFile }