web-dev-qa-db-fra.com

renommer des dossiers à l'aide d'un fichier .txt

Je travaille dans mon terminal en utilisant bash essayant de renommer les dossiers:

1
2
3
4
5

J'aimerais les renommer en fonction d'un fichier.txt:

a 2
c 3
d 5
e 1
b 4

L'ordre dans le fichier .txt est complètement aléatoire. J'espère trouver un moyen de renommer le dossier pour qu'il devienne:

1 > e
2 > a
3 > c
4 > b
5 > d

Est-ce qu'il y a un moyen de faire ça?

Merci beaucoup!

7
Ditte

En supposant que les noms dans la liste n'incluent pas d'espaces , à l'exception de entre les noms, le script ci-dessous renommera les dossiers d’un fichier texte de manière récursive . Il lira les lignes du fichier, les scindera en deux (nouveau nom, ancien nom), renommera les dossiers d’origine nommés par la seconde chaîne la ligne, dans la première chaîne de la ligne.

Comme cela a été mentionné récursivement , il le fera de bas en haut dans l’arborescence. Cela évite les problèmes dans le script, en essayant de renommer des dossiers dans des dossiers parents éventuellement déjà renommés.

#!/usr/bin/env python
import os
import shutil

# -- set the (absolute) path to the targeted folder below
dr = "/home/jacob/Bureaublad/testfolder"
# -- set the path to the textfiles below
ren = "/home/jacob/Bureaublad/testfolder/renfile.txt"

renlist = [cpl for cpl in [l.split() for l in open(ren).readlines()] if cpl]
currnames = [r[1] for r in renlist]

for root, dirs, files in os.walk(dr, topdown = False):
    for dr in dirs:
        try:
            # look up the name, pass if not in the list
            i = currnames.index(dr)
        except ValueError:
            pass
        else:
            newname = renlist[i][0]
            shutil.move(root+"/"+dr, root+"/"+newname)

Comment utiliser

  1. Copiez le script dans un fichier vide (dans un éditeur en texte brut ), enregistrez-le sous le nom rename.py
  2. Dans la section head du script, définissez les véritables chemins d'accès au fichier texte et au répertoire.
  3. lancez le par la commande (dans un terminal):

    python /path/to/rename.py
    

Explication

Le scénario:

  • crée une liste de couples de noms : nouveau nom/ancien nom
  • en utilisant os.walk() de python, il parcourt vos répertoires de manière récursive, de bas en haut.
  • Si le nom du dossier correspond au deuxième élément d'un couple de noms, il renomme le dossier en prénom.
  • Si le nom du dossier ne figure pas dans la liste, il ne sera pas modifié.
4
Jacob Vlijm

Vous pouvez utiliser xargs avec mv:

xargs -r -a /path/to/file.txt -L1 mv

(en supposant que vous êtes dans le répertoire où se trouvent les fichiers).

xargs convertit les entrées en arguments d'une commande.

  • -a foo pour lire l'entrée de foo.
  • -L1 pour utiliser exactement une ligne d'entrée par appel de commande.
  • -r pour éviter d'exécuter la commande si la ligne est vide

Par exemple, utilisez echo mv au lieu de mv pour afficher les commandes en cours d'exécution:

$ xargs -r -a foo.txt -L1 echo mv
mv a 2
mv c 3
mv d 5
mv e 1
mv b 4

Vous pouvez également utiliser l'option -p pour confirmer xargs avant d'exécuter la commande:

$ xargs -r -p -a foo.txt -L1 mv
mv a 2 ?...n
mv c 3 ?...n
mv d 5 ?...y
mv e 1 ?...mv: cannot stat ‘d’: No such file or directory
n
mv b 4 ?...
6
muru

Le fichier a.txt contient une entrée par ligne. Par conséquent, les noms répertoriés ne contiennent pas de caractère \n (nouvelle ligne), n'est-ce pas?

Une ligne contient 2 noms séparés par un caractère espace, de sorte que les noms ne contiennent pas espace caractère, non? (ou une autre possibilité serait d’utiliser une longueur fixe pour les noms listés).

Essayez ceci si les noms ne contiennent ni \n ni space caractères:

awk '{printf("%s\0%s\0",$2,$1)}' a.txt | xargs -0 -L 2 mv

awk est utilisé pour inverser l'ordre des noms dans les lignes lues dans le fichier a.txt. \0 est utilisé pour séparer les noms lorsqu'ils sont imprimés sur une sortie standard.

xargs lit l'entrée standard:

  • -0: \0 sert de séparateur pour les éléments lus à partir de l'entrée standard.
  • -L 2 mv: mv la commande est appelée avec 2 paramètres à la fois.

Le test:

$ ls -al
total 40
drwxrwxr-x  7 stacko stacko  4096 May 31 11:25 .
drwxrwxr-x 21 stacko stacko 12288 May 31 11:23 ..
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 1
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 2
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 3
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 4
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 5
-rw-rw-r--  1 stacko stacko    20 May 31 11:24 a.txt
$ cat a.txt
a 2
c 3
d 5
e 1
b 4
$ awk '{printf("%s\0%s\0",$2,$1)}' a.txt | xargs -0 -L 2 mv -v
'2' -> 'a'
'3' -> 'c'
'5' -> 'd'
'1' -> 'e'
'4' -> 'b'
$ ls -al
total 40
drwxrwxr-x  7 stacko stacko  4096 May 31 11:26 .
drwxrwxr-x 21 stacko stacko 12288 May 31 11:23 ..
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 a
-rw-rw-r--  1 stacko stacko    20 May 31 11:24 a.txt
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 b
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 c
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 d
drwxrwxr-x  2 stacko stacko  4096 May 31 11:25 e
2
Jay jargot

Dans le cas simple que vous montrez ci-dessus, où chaque ligne a deux "mots", le répertoire cible et le nouveau nom, et où ni l'une ni l'autre ne peut contenir aucun espace, vous pouvez simplement faire:

while read -r from to; do mv "$from" "$to"; done < file 

Cela lira chaque ligne dans file assignera la première chaîne (jusqu'au premier espace blanc) à $from et le reste de la ligne à $to, puis exécutera mv sur chacun des leur.

2
terdon