rm -rf tous les fichiers et tous les fichiers cachés sans. & .. Erreur

83

rm -rf /some/path/* supprime tous les fichiers non cachés de ce répertoire (et de ses sous-répertoires).

rm -rf /some/path/.* supprime tous les fichiers cachés dans ce répertoire (mais pas les sous-répertoires) et génère également l'erreur / avertissement suivant:

rm: cannot remove directory: `/some/dir/.'
rm: cannot remove directory: `/some/dir/..'

Quelle est la bonne façon de supprimer tous les fichiers et dossiers cachés et non cachés dans un répertoire cible sans recevoir l'avertissement / l'erreur concernant .et ..?

Jake Wilson
la source

Réponses:

40

Vous pouvez toujours envoyer des messages d'erreur à /dev/null

rm -rf /some/path/.* 2> /dev/null

Tu pourrais aussi juste

rm -rf /some/path/
mkdir /some/path/

... alors vous n'aurez pas à vous soucier des fichiers cachés.

maux de tête
la source
2
Mais que faire si je veux seulement supprimer les fichiers cachés?
CMCDragonkai
@CMCDragonkai cela devrait être une question différente, mais vous pouvez trouver la solution dans la réponse de Gilles ( rm ..?* .[!.]*devrait le faire).
Evilsoup
15
La suppression et la recréation du répertoire ne posent pas le risque que les autorisations de fichiers ne soient pas correctes par la suite (particulièrement important dans les environnements de serveur). Qui pourrait-on créer automatiquement le dossier avec les mêmes autorisations qu'auparavant?
Yo Ludke
1
@YoLudke Vous avez tout à fait raison. Dans de nombreux cas, ce n'est pas grave, mais supprimer et recréer un dossier n'est pas sémantiquement équivalent à vider ce dossier. alors faites attention à le faire!
Thomas
La suppression du répertoire n'est pas toujours possible. Dans mon cas, le répertoire est un volume fixe, et bien que je puisse faire tout ce que je veux à l'intérieur du volume, je ne peux pas changer le volume lui-même à partir du conteneur.
dovidweisz le
84

*correspond à tous les fichiers .[!.]*autres que les fichiers à points , à tous les fichiers à points sauf les .fichiers dont le nom commence par .., et à ..?*tous les fichiers à points excepté ... Ensemble, ils correspondent à tous les fichiers autres que .et ... Si l’un de ces trois modèles ne correspond à rien, il se développe; rm -fne se soucie pas des arguments inexistants, donc cela n'a pas d'importance.

rm -rf ..?* .[!.]* *

Vous pouvez également utiliser find. Ceci est plus complexe mais présente l'avantage de fonctionner même s'il y a tellement de fichiers que les caractères génériques ci-dessus s'étendent au-delà de la limite de longueur de ligne de commande de votre système.

find . -name . -o -prune -exec rm -rf -- {} +

Vous trouverez peut-être plus clair de supprimer et de recréer le répertoire. Cela présente l'avantage (ou l'inconvénient, selon le cas) de créer un répertoire vide, même si un autre programme crée simultanément des fichiers dans le répertoire d'origine.

Gilles
la source
8
Cela devrait être la réponse acceptée, car elle empêche la traversée des parents et leur suppression éventuelle.
rbellamy
L’ findalternative renvoie «success» même si certains fichiers ne sont pas supprimés avec succès; pas bon pour le script.
Franklin Yu
En ce qui concerne votre deuxième findcommande, la page de manuel relative à find États "Parce que -delete implique -depth, vous ne pouvez pas utiliser utilement -prune et -delete ensemble." - mais vous utilisez -prune -delete?
Doktor J
@DoktorJ En effet, -prunene fait rien ici. Et en relisant, je constate que je n’ai pas répondu correctement à la question: j’ai pris soin de ne pas récidiver, mais la question demande explicitement une suppression récursive. J'ai corrigé ma réponse.
Gilles
2
@haylem Dans zsh, vous devez écrire .[^.]*au lieu de .[!.]*lorsque la substitution d'historique est activée (ce qui est le cas par défaut de manière interactive, mais pas dans les scripts), car zsh analyse en !tant que référence d'historique. Mais en zsh, vous n'en auriez pas besoin en premier lieu, vous pouvez simplement utiliser *(D)pour inclure des fichiers de points (sans .ou ..) dans la correspondance avec le caractère générique.
Gilles
21

Je viens de me rendre compte que c’est le moyen le plus pratique dans la plupart des distributions Linux:

ls -A1 | xargs rm -rf

-A= tout lister sauf . et..

-1 = mettre chaque article sur une ligne

Godzillante
la source
4
L’inconvénient que je vois est le suivant: vous devez "cd" dans le répertoire pour le faire.
Kumar
ls -A1 /your/path/ | xargs rm -rfdevrait postuler
godzillante
Nope..il n'aide pas - Par exemple: ls -A1 ~ / test / | xargs rm -rf cette commande supprime les fichiers que je suis actuellement 'cd dans' .. pas dans le répertoire ~ / test.
kumar
5
Cela ne fonctionne pas si l'un des noms de fichier contient des blancs, des nouvelles lignes, des guillemets ou des barres obliques inverses.
Stéphane Chazelas
1
-1 à cause du commentaire ci-dessus. ↑↑↑↑↑↑↑
Quelque chose de
15

Changez l’ dotgloboption de votre shell et utilisez *, ou utilisez quelque chose comme find.

find somedir -mindepth 1 -delete
Ignacio Vazquez-Abrams
la source
2
Ou vous pouvez simplement rm -rf /some/diret ensuite créer un nouveau répertoire vide à sa place.
Tripleee
Meilleure option jusqu'à présent. Très sûr puisque vous spécifiez explicitement le chemin du répertoire.
Yanick Girouard
4

Cela devrait fonctionner comme @Gilles mais plus compact:

rm -rf {,.[!.],..?}*

ou

rm -rf dir/to/files/{,.[!.],..?}*

devrait également ajouter un ifpour une utilisation dans les scripts juste pour être sûr:

if [ -d "$DIR" ]; then
    rm -rf ${DIR}/{,.[!.],..?}*
fi
Paweł Prażak
la source
1
Curieusement, en tant qu'alias bash sur Ubuntu 16.04 LTS, la réponse précédente ne fonctionnait pas. Cependant, alias cleandir='rm -rf {,.[!.],..?}*'fait.
Steven Ventimiglia
3

Trouvez est votre ami.

find ! -name '.' ! -name '..' -delete

% find ! -name '.' ! -name '..'
./test
./test4
./test4/.test6
./test3
./.test5
./test2
% find ! -name '.' ! -name '..' -delete    
% find ! -name '.' ! -name '..'     
%             

Si vous souhaitez utiliser de manière récursive une autre recherche dans votre répertoire actuel ($ PWD), ajoutez un chemin juste après la findcommande; par exemple find /path ! -name '.' ! -name '..' -delete. Si vous souhaitez uniquement réduire le nnombre de répertoires, utilisez l' -maxdepth noption juste après le /pathparamètre.

La commande ci-dessus a été testée sur un système Ubuntu 13.04. Cela fonctionnera probablement sur d’autres systèmes linux modernes.

laebshade
la source
Pour supprimer tous les répertoires du répertoire actuel, vous pouvez le faire.find . ! -name '.' ! -name '..' -type d -delete
Andy
2

Quelle est la bonne façon de supprimer tous les fichiers et dossiers cachés et non cachés dans un répertoire cible sans recevoir l'avertissement / l'erreur concernant. et ..?

En supposant que le répertoire en question est ./dir, alors

rm -rf ./dir

supprimerait de ./dirmanière récursive tous les fichiers , y compris les fichiers et répertoires cachés, y compris le ./dirrépertoire lui-même.

Si vous ne souhaitez pas supprimer le répertoire lui-même, vous pouvez simplement le recréer par la suite ou utiliser

find ./dir -mindepth 1 -delete

ou si vous findne supportez pas -delete,

find ./dir -mindepth 1 -depth -exec rm -rf {} ';'

Utiliser -mindepth 1vous permet de conserver le répertoire de niveau supérieur ./dir.

Kusalananda
la source
cela devrait être marqué comme la meilleure réponse
kitingChris
1

Je vous suggère d'expérimenter avec

Turn- ON points (fichiers cachés)

  • ensemble dotglob

    shopt -s dotglob

Turn- OFF points

  • non fixé dotglob

    shopt -u dotglob

Cette méthode fonctionnait exactement comme je le souhaitais pour une commande de copie ne contenant pas les répertoires cachés.

    shopt -s    dotglob
    cp    -rvn  ./$from/*  ./$too/
    shopt -u    dotglob

Alors j'ai fait une suppression (suppression), et oups ...

    shopt -s    dotglob
    rm -fr ../message_splitter--044a/*
    shopt -u    dotglob

... ça marche aussi!

Il me semble que votre cher lecteur ne peut pas voir le message_splitterrépertoire. De toute façon, il a un .svndossier qui doit être supprimé et copié dans.

De la manpage ...

dotglob Si défini, bash inclut les noms de fichiers commençant par un "." dans les résultats de l'expansion du chemin d'accès.

références:

volonté
la source
-2

Essayez ce code:

Dirlist=``find /some/path/ -type d -name '.[^.]*'`
for HiddenDir in $Dirlist
do
    rm -rf $HiddenDir
done
taille
la source