переименование папок с использованием .txt-файла

Я работаю в своем терминале, используя bash, чтобы переименовать папки:

1 2 3 4 5 

Я хотел бы переименовать их в соответствии с файлом a.txt:

 a 2 c 3 d 5 e 1 b 4 

Порядок в файле .txt полностью случайный. Я надеюсь найти способ, которым я могу переименовать папку, чтобы они стали:

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

Есть какой-либо способ сделать это?

Большое спасибо!

Предполагая, что имена в списке не включают пробелы , кроме как между именами, сценарий ниже будет переименовывать папки из текстового файла рекурсивно . Он прочитает строки файла, разделит их на два (новое имя, старое имя), переименуйте папки, имена которых по второй строке в строке, в первую строку в строке.

Он будет делать это, как упоминалось рекурсивно , снизу вверх в дереве каталогов. Это предотвращает проблемы в скрипте, пытаясь переименовать папки в возможно уже переименованных родительских папках.

 #!/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) 

Как использовать

  1. Скопируйте сценарий в пустой файл (в текстовом редакторе), сохраните его как rename.py
  2. В главном разделе скрипта задайте реальные пути к текстовому файлу и директории
  3. запустите его командой (в терминале):

     python /path/to/rename.py 

объяснение

Сценарий:

  • создает список имен- пар : newname / oldname
  • используя os.walk() python, он просматривает ваши каталоги рекурсивно, снизу вверх.
  • Если имя папки совпадает с вторым элементом пары имени, она переименовывает папку в имя.
  • Если имя папки отсутствует в списке, оно будет не тронуто.

Вы можете использовать xargs с mv :

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

(если вы находитесь в каталоге, где находятся файлы).

xargs преобразует входные данные в аргументы для команды.

  • -a foo для чтения ввода из foo .
  • -L1 чтобы использовать только одну строку ввода для каждого вызова команды.
  • -r чтобы избежать запуска команды, если строка пуста

Например, используя echo mv вместо mv чтобы показать выполняемые команды:

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

Вы также можете использовать опцию -p чтобы подтвердить подтверждение xargs перед запуском команды:

 $ 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 ?... 

В файле a.txt есть одна запись на строку, поэтому перечисленные имена не содержат символ \n (новая строка), правильно?

Строка содержит 2 имени, разделенных пробелом , поэтому имена не содержат пробела , не так ли? (или другая возможность – использовать фиксированную длину для названных имен).

Попробуйте это, если имена не содержат ни \n ни space символов:

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

awk используется для изменения порядка имен в строках, считанных из файла a.txt . \0 используется для разделения имен при печати на стандартный вывод.

xargs считывает стандартный ввод:

  • -0 : \0 используется как разделитель для элементов, считанных со стандартного ввода
  • Команда -L 2 mv : mv вызывается с двумя параметрами за раз.

Тест:

 $ 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 

В простом случае, который вы показываете выше, где каждая строка имеет два слова, целевую директорию и новое имя и где ни одно из них не может содержать пробелов, вы можете просто сделать:

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

Это будет читать каждую строку в file назначая первую строку (до первого пробела) до $from и остальную часть строки до $to а затем запускать mv для каждого из них.