web-dev-qa-db-fra.com

Comment renommer (afficher) tous les fichiers et sous-répertoires d'un répertoire?

Je veux créer un script pour "afficher" tous les fichiers et répertoires d’un répertoire donné en une fois, par exemple. ./unhide test.

test/
├── sub1
│   └── .hiddenfile1
└── sub2
    └── .hiddendir
        ├── .hiddendirsub
        ├── .hiddenfile2
        └── not.hidden

Résultat souhaité:

test/
├── sub1
│   └── hiddenfile1
└── sub2
    └── hiddendir
        ├── hiddendirsub
        ├── hiddenfile2
        └── not.hidden

Comment puis je faire ça?

Je suis encore nouveau dans ce domaine et j'essaie de trouver une solution en utilisant find, mais je suis bloqué à -exec et rename (ou mv) car j'ai toujours du mal à comprendre comment cette combinaison fonctionne. :( Alors, j'apprécierais que quelqu'un ici puisse donner une solution et une explication détaillée également. Merci.

5
Lukman Hakim

Vous pouvez le faire avec find comme suit:

find /path/to/test -depth -name ".*" -execdir rename -n 's|/\.|/|' {} +

Ceci n’imprime que les actions de changement de nom, s’il indique ce que vous voulez supprimer de l’option -n.

Des explications

  • -depth - permet à find de traiter de bas en haut, en renommant les fichiers avant leurs répertoires parents
  • -name ".*" - laisse find rechercher des fichiers ( tout est un fichier ) commençant par un point - le point est littéral ici, car il ne s'agit pas d'une expression régulière
  • -execdir … + - exécute dans le répertoire du fichier correspondant
  • rename 's|/\.|/|' {} - remplace la première occurrence de "/." du chemin du fichier correspondant (espace réservé de find qui correspond à {}) par "/", supprimant essentiellement le point du début du nom de fichier
    Ce serait par exemple rename 's|/\.|/|' ./.hiddenfile1 dans votre cas, il serait renommé ./hiddenfile1.

Exemple d'exécution

$ tree -a
.
├── sub1
│   └── .hiddenfile1
└── sub2
    └── .hiddendir
        ├── .hiddendirsub
        ├── .hiddenfile2
        └── not.hidden

$ find ~/test -depth -name ".*" -execdir rename 's|/\.|/|' {} +
$ tree -a
.
├── sub1
│   └── hiddenfile1
└── sub2
    └── hiddendir
        ├── hiddendirsub
        ├── hiddenfile2
        └── not.hidden

Utilisation dans un script

Dans un script, vous pouvez simplement utiliser des paramètres de position à la place du chemin, il peut être relatif ou absolu - rappelez-vous simplement de citation correcte :

#!/bin/bash
find "$1" -depth -name ".*" -execdir rename -n 's|/\.|/|' {} +
7
dessert
$ tree -a test
test
├── .alsohidden
├── sub1
│   └── .hiddenfile1
└── sub2
    ├── .hiddendirsub
    ├── .hiddenfile2
    └── not.hidden

3 directories, 4 files

$ find test/ -depth -name ".*" -exec rename -n 's|(.*/)\.(.*)|$1$2|' {} +
rename(test/.alsohidden, test/alsohidden)
rename(test/sub2/.hiddendirsub, test/sub2/hiddendirsub)
rename(test/sub2/.hiddenfile2, test/sub2/hiddenfile2)
rename(test/sub1/.hiddenfile1, test/sub1/hiddenfile1)
  • find test/ commencer les chemins avec test/, recherche récursive à partir de ce chemin
  • -depth volé de réponse du dessert - semblait être une bonne idée
  • -name ".*" nom de fichier commence par .
  • -exec command {} + exécuter command sur les fichiers trouvés, en construisant une liste d'arguments.
  • rename -n ne fait rien, affiche uniquement ce qui sera fait (supprimez -n après le test pour renommer réellement)
  • s|old|new| remplace old par new
  • (.*/)\.(.*) enregistrer tous les caractères jusqu'au dernier séparateur de répertoire inclus, /, ignorer un . littéral, enregistrer tous les caractères suivants
  • $1$2 imprimer les motifs sauvegardés
3
Zanna