Переименуйте файлы в нескольких каталогах в имя каталога

У меня есть что-то вроде этого:

v_1/file.txt
v_2/file.txt
v_3/file.txt
...

и я хочу переименовать эти файлы примерно так:

v_1.txt
v_2.txt
v_3.txt
...

в том же каталоге.

Думаю, я могу использовать rename, но я не могу понять, как использовать его с одновременным переименованием папок и файлов.


person giskou    schedule 13.01.2013    source источник
comment
Stack Overflow не является сервисом для написания кода. Пожалуйста, покажите свой код. Поскольку переполнение стека скрывает от вас причину закрытия: Вопросы, требующие помощи в отладке (почему этот код не работает?), должны включать желаемое поведение, конкретную проблему или ошибку и кратчайший код, необходимый для их воспроизведения в самом вопросе. . Вопросы без четкой формулировки проблемы бесполезны для других читателей. См. раздел Как создать минимальный, полный и проверяемый пример.   -  person jww    schedule 28.03.2018


Ответы (3)


Результат может быть достигнут с помощью цикла bash for и mv:

for subdir in *; do mv $subdir/file.txt $subdir.txt; done;

Обратите внимание, что приведенное выше решение не будет работать, если имя каталога содержит пробелы. Связанная ссылка.

Другое решение, основанное на комментариях (которое также работает для каталогов с пробелами в имени):

find . -type d -not -empty -exec echo mv \{\}/file.txt \{\}.txt \;
person Csq    schedule 13.01.2013
comment
$subdir должно быть "$subdir" и удалить пустые папки find . -type d -empty -exec rm -rf \{\} \; - person giskou; 13.01.2013
comment
@giskou Если вам нравится печатать. Одно переименование s#/file## намного проще вводить, и оно находится на правильном уровне абстракции. Повторение одного и того же цикла оболочки всю свою жизнь для переименования файлов быстро устаревает. - person tchrist; 13.01.2013
comment
@giskou: я не понимаю, почему пустые папки являются проблемой, потому что mv просто не работает. Кроме того, удаление пустого каталога с помощью rm -rf является излишним, вы можете просто использовать rmdir, это безопаснее. - person Csq; 13.01.2013
comment
@giskou: команда find над ней также может быть изменена для выполнения задачи: find . -type d -not -empty -exec echo mv \"\{\}/file.txt\" \"\{\}.txt\" \; - person Csq; 13.01.2013
comment
У меня не работает: $ find . -type d -not -empty -exec echo mv \{\}/*.m4a \{\}.m4a \; - person ; 01.07.2016
comment
Обратите внимание, что с echo в нем он фактически ничего не будет делать напрямую, плюс он также пытается действовать в текущем каталоге, а не только в подкаталогах. Вот как это выглядит с обоими фиксированными: find ./* -type d -not -empty -exec mv \{\}/file.txt \{\}.txt \; - person MalcolmOcean; 06.01.2020
comment
очередь предложений редактирования кажется заполненной, но да, чтобы она работала, она должна быть for subdir in *; do mv $subdir/file.txt "$subdir".txt; done; - person aechchiki; 09.06.2020

Вы можете использовать rnm. Команда будет:

rnm -fo -dp -1 -ns '/pd0/.txt' -ss '\.txt$' /path/to/the/directory

-fo подразумевает только файловый режим.

-dp глубина каталога. -1 делает его рекурсивным для всех подкаталогов.

-ns подразумевает строку имени, то есть новое имя файла.

/pd0/ — это непосредственный родительский каталог файла, который подлежит операции переименования.

-ss — строка поиска (регулярное выражение). '\.txt$' регулярное выражение ищет файл с .txt в конце имени файла.

/path/to/the/directory это путь, по которому находятся каталоги v_1, v_2.... Вы также можете передать каталоги ( v_1, v_2 ...) вместо пути к родительскому каталогу. Например:

#from inside the parent directory
rnm -fo -dp -1  -ns '/pd0/.txt' -ss '\.txt$' v_* 
person Jahid    schedule 29.01.2016

Мне кажется довольно простым:

$ mkdir /tmp/sandbox
$ cd /tmp/sandbox

$ mkdir v_{1,2,3}
$ touch v_{1,2,3}/file.txt

$ rename -v 's#/file##' v_{1,2,3}/file.txt
rename v_1/file.txt v_1.txt
rename v_2/file.txt v_2.txt
rename v_3/file.txt v_3.txt

$ ls -F
v_1/  v_1.txt    v_2/  v_2.txt    v_3/  v_3.txt
person tchrist    schedule 13.01.2013
comment
вложенных папок около 130, а не только 3: P - person giskou; 13.01.2013
comment
@giskou Я не понимаю, почему это важно: я просто продемонстрировал, что техника работает. Количество подкаталогов не имеет значения, если только вы не достигнете предела xargs, и даже это тривиально, поскольку Perl rename будет читать имена файлов на стандартном вводе. - person tchrist; 13.01.2013
comment
Я больше люблю bash, чем perl и регулярные выражения. Если бы вы могли подробно объяснить свою технику... Я действительно не знаю, что она делает: P - person giskou; 13.01.2013
comment
@gisou Вы просто применяете стандартную команду поиска и замены, как и в любом редакторе, поэтому s/foo/bar/g изменяет все экземпляры foo в именах файлов на экземпляры bar и т. д. - person tchrist; 13.01.2013