Могу ли я переименовать файлы в папке с именем родительской папки? [дубликат]

На этот вопрос уже есть ответ здесь:

Это уникальная ситуация, которая можно лучше объяснить на примере

Пример 1 скажем, у меня есть папка с именем A , B.mkv и C.srt ] - это два файла в папке, я хочу переименовать эти файлы в A.mkv и A.srt .

практическим примером может быть папка под названием American Sniper (2014) и American.Sniper.2014.1080p.BluRay.x264.YIFY.mkv и American.Sniper .2014.Subtitle.BluRay.ShaAnig.srt - это два файла в папке, нужно переименовать эти файлы в American Sniper (2014) .mkv и American Sniper (2014) .srt

Пример 2

Это должно быть рекурсивно скажем, у меня есть папка с именем A , B и C - это два Sub -папки в папке A .содержимое B и C выглядит следующим образом

Example

Должно быть преобразовано в

Result

Даже когда я запускаю алгоритм / сценарий / команду в папке A

Третье, что он должен сделать, это игнорировать скрытые файлы

пример

Example

должен привести к

Result

, наконец, он должен работать с несколькими папками одновременно

2
задан 7 April 2017 в 13:38

2 ответа

Существует несколько способов приблизиться к этому вопросу. Прочитайте инструкции тщательно для лучших результатов.

В этом ответе:

  1. Подход Python
  2. find + bash подход
  3. подход только для удара с globstar

1. Решение Python

Python является довольно мощным языком для системного администрирования, и пересекающее дерево каталогов может быть сделано через os.walk() функция. В сценарии, представленном ниже, мы делаем точно, что - мы находим все файлы и воздействуем на каждого из них, путем определения полного пути в каждый файл, расширение файла, и переименования его через os.rename() функция.

Содержание сценария

#!/usr/bin/env python3
import os,sys

def get_all_files(treeroot):
    for dir,subdirs,files in os.walk(treeroot):
         for f in files: 
             if f in __file__: continue
             fullpath = os.path.realpath( os.path.join(dir,f) )
             extension = fullpath.split('.')[-1]
             newpath = os.path.join(dir, dir + '.' + extension)
             print('Move ' + fullpath + ' to ' + newpath   )
             # os.rename(fullpath,newpath)


def main():
    top_dir="."
    # If directory not given, assume cwd
    if len(sys.argv) == 2: top_dir=sys.argv[1]
    get_all_files(top_dir)

if __name__ == '__main__' : main()

Примечание: очень очень важный то, что для фактического переименования файлов необходимо удалить # прежде # os.rename(fullpath,newpath).

Установка сценария

Все стандартные правила для сценариев применяются: - сохраняют его как add_location_name.py в каталоге самого верхнего уровня - делают исполняемый файл с chmod +x ./add_location_name.py - выполненный с ./add_location_name.py

Тестирование сценария

Вот пример того, как это работает на практике. Я создал каталог с двумя другими, Movie A (2016) и Movie B (2016). В них у них обоих есть два файла. Наш сценарий живет в том же каталоге:

$ tree                                                        
.
├── add_location_name.py
├── Movie A (2014)
│  ├── filea.mkv
│  └── fileb.srt
└── Movie B (2016)
    ├── filea.mkv
    └── fileb.srt

Таким образом, когда мы запускаем скрипт, мы будем видеть следующий вывод:

$ ./add_location_name.py                                                                                              
Move /home/xieerqi/testdir/Movie A (2014)/fileb.srt to ./Movie A (2014)/./Movie A (2014).srt
Move /home/xieerqi/testdir/Movie A (2014)/filea.mkv to ./Movie A (2014)/./Movie A (2014).mkv
Move /home/xieerqi/testdir/Movie B (2016)/fileb.srt to ./Movie B (2016)/./Movie B (2016).srt
Move /home/xieerqi/testdir/Movie B (2016)/filea.mkv to ./Movie B (2016)/./Movie B (2016).mkv

2. Решение через команду находки и - исполнительный флаг

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

В первую очередь, позвольте мне дать Вам решение:

find -type f -exec bash -c 'fp=$(dirname "$1");fn=$(basename "$fp");px="${1##*.}";mv "$1" "$fp"/"$fn"."$px"' sh "{}" \;

Взгляды, долгие и страшные, правильно? Но не волнуйтесь, отпускает по тому, как это работает.

Разделение команды

В первую очередь, необходимо распознать, что существует две вещи, продолжающиеся: find команда определяет местоположение всех файлов и bash часть - то, что на самом деле делает часть переименования. На внешней стороне, что мы видим, простая команда:

find -type f -exec <COMMAND> \;

Это только находит все файлы (никакие каталоги или символьные ссылки) и называет некоторую другую команду каждый раз, когда она находит файл. В этом случае определенная КОМАНДА, которую мы имеем, bash.

Таким образом, что делает bash -c 'fp=$(dirname "$1");fn=$(basename "$fp");px="${1##*.}";mv "$1" "$fp"/"$fn"."$px"' sh "{}" часть делает? Ну, в первую очередь, распознайте структуру: bash -c 'command1;command2' arg0 arg1. Каждый раз, когда -c флаг используется первый параметр командной строки arg0 будет установлен как $0 , окружите имя, таким образом, это не важно, но "{}" важно. Это - заключенный в кавычки заполнитель для имени файла это find передаст как аргумент bash.

На внутренней части удара управляют, чтобы мы извлекли путь к файлу fp=$(dirname "$1") , имя каталога fn=$(basename "$fp"), и расширение файла или префикс px="${1##*.}". Все это удается действительно приятно, так как мы выполняем команду от каталога самого верхнего уровня (очень важный!). Наконец, mv "$1" "$fp"/"$fn"."$px"' sh "{}" переименует исходный файл это find дал нам новому имени файла, с чем мы растем "$fp"/"$fn"."$px" использование всех тех переменных.

Пример операции

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

$ tree
.
├── Movie A (2014)
│  ├── filea.mkv
│  └── fileb.srt
└── Movie B (2016)
    ├── filea.mkv
    └── fileb.srt

2 directories, 4 files

И если мы выполняем команду, с echo вместо mv мы видим, что каждое имя файла переименовано соответственно.

$ find -type f -exec bash -c 'fp=$(dirname "$1");fn=$(basename "$fp");px="${1##*.}";echo "$1" "$fp"/"$fn"."$px"' sh ">
./Movie A (2014)/fileb.srt ./Movie A (2014)/Movie A (2014).srt
./Movie A (2014)/filea.mkv ./Movie A (2014)/Movie A (2014).mkv
./Movie B (2016)/fileb.srt ./Movie B (2016)/Movie B (2016).srt
./Movie B (2016)/filea.mkv ./Movie B (2016)/Movie B (2016).mkv

Помните: вышеупомянутое использование команды echo только для тестирования. Когда Вы используете mv нет никакого вывода, таким образом, команда тиха.


3. Более простой подход: Bash и звезда шарика

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

for f in */* ;do fp=$(dirname "$f"); ext="${f##*.}" ; echo "$f" "$fp"/"$fp"."$ext" ;done

Снова, та же идея - замена echo с mv когда Вы уверены, что это работает правильно.

Результаты испытаний являются тем же:

$ tree                                                                                                                
.
├── add_location_name.py
├── Movie A (2014)
│  ├── filea.mkv
│  └── fileb.srt
└── Movie B (2016)
    ├── filea.mkv
    └── fileb.srt

2 directories, 5 files
$ for f in */* ;do fp=$(dirname "$f"); ext="${f##*.}" ; echo "$f" "$fp"/"$fp"."$ext" ;done                            
Movie A (2014)/filea.mkv Movie A (2014)/Movie A (2014).mkv
Movie A (2014)/fileb.srt Movie A (2014)/Movie A (2014).srt
Movie B (2016)/filea.mkv Movie B (2016)/Movie B (2016).mkv
Movie B (2016)/fileb.srt Movie B (2016)/Movie B (2016).srt
3
ответ дан 2 December 2019 в 01:43

Учитывая

$ tree
.
└── A
    ├── B
    │   ├── somefile
    │   ├── T.txt
    │   ├── X.srt
    │   └── Z.mkv
    └── C
        ├── somefile
        ├── T.txt
        ├── W.mkv
        └── Y.srt

3 directories, 8 files

затем

$ find A -type f \( -name '*.mkv' -o -name '*.srt' \) -not -name '.*' -exec sh -c '
  for f; do 
    dir="${f%/*}" ; ext="${f##*.}" ; new="${dir##*/}"
    echo mv -- "$f" "${dir}/${new}.${ext}"
  done' sh {} +
mv -- A/C/Y.srt A/C/C.srt
mv -- A/C/W.mkv A/C/C.mkv
mv -- A/B/Z.mkv A/B/B.mkv
mv -- A/B/X.srt A/B/B.srt

(удаляют echo, после того как Вы уверены , это собирается сделать то, что Вы хотите).

3
ответ дан 2 December 2019 в 01:43

Другие вопросы по тегам:

Похожие вопросы: