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

На этот вопрос уже есть ответ: переименуйте файл в имя родительского каталога в терминах 5 ответов

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

Пример 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 - две подпапки в папке A. содержимое B и C выглядит следующим образом

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

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

Третья вещь, которую он должен делать, это Игнорировать скрытые файлы

example

Example [!d13]

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

Example [!d13]

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

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

14 ответов

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

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

Подход Python find + bash подход только для bash-подхода с globstar [ ! d6]

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 - запустить с [ f18]

Тестирование скрипта

Вот пример того, как это работает на практике. Я создал каталог с двумя другими, 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 и команды -exec

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

Прежде всего позвольте мне дать вам решение:

find -type f -exec bash -c 'fp=$(dirname "$1");fn=$(basename "$fp");px="${1##*.}";mv "$1" "$fp"/"$fn"."$px"' sh "{}" \;
[d21 ] Выглядит долго и страшно, не так ли?

Распаковка команды

Прежде всего вам нужно признать, что происходит две вещи: команда 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, имя оболочки, поэтому оно не имеет значения, но важно "{}". Это цитируемый placeholder для имени файла, который find будет передан как аргумент bash.

Внутри команды 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 и glob star

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

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

Опять же, ту же идею - замените echo на [ f44], когда вы уверены, что он работает правильно.

Результаты испытаний одинаковы:

$ 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
ответ дан 22 May 2018 в 23:54
  • 1
    последняя команда работала отлично, спасибо большое – Sumeet Deshmukh 7 April 2017 в 19:25

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

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

Подход Python find + bash подход только для bash-подхода с globstar [ ! d6]

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 и команды -exec

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, имя оболочки, поэтому оно не имеет значения, но важно "{}". Это цитируемый placeholder для имени файла, который find будет передан как аргумент bash.

Внутри команды 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 и glob star

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

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
ответ дан 18 July 2018 в 15:23

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

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

Подход Python find + bash подход только для bash-подхода с globstar [ ! d6]

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 и команды -exec

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, имя оболочки, поэтому оно не имеет значения, но важно "{}". Это цитируемый placeholder для имени файла, который find будет передан как аргумент bash.

Внутри команды 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 и glob star

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

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
ответ дан 24 July 2018 в 20:37

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

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

Подход Python find + bash подход только для bash-подхода с globstar [ ! d6]

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 и команды -exec

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, имя оболочки, поэтому оно не имеет значения, но важно "{}". Это цитируемый placeholder для имени файла, который find будет передан как аргумент bash.

Внутри команды 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 и glob star

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

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
ответ дан 31 July 2018 в 23:39

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

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

  1. Подход Python
  2. find + bash подход
  3. подход, основанный только на bash с 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 и команды -exec

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, имя оболочки, поэтому оно не имеет значения, но важно "{}". Это цитируемый placeholder для имени файла, который find будет передан как аргумент bash.

С внутренней стороны команды 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 и glob

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

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 August 2018 в 18:36

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

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

  1. Подход Python
  2. find + bash подход
  3. подход, основанный только на bash с 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 и команды -exec

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, имя оболочки, поэтому оно не имеет значения, но важно "{}". Это цитируемый placeholder для имени файла, который find будет передан как аргумент bash.

С внутренней стороны команды 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 и glob

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

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
ответ дан 3 August 2018 в 20:55

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

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

  1. Подход Python
  2. find + bash подход
  3. подход, основанный только на bash с 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 и команды -exec

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, имя оболочки, поэтому оно не имеет значения, но важно "{}". Это цитируемый placeholder для имени файла, который find будет передан как аргумент bash.

С внутренней стороны команды 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 и glob

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

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
ответ дан 5 August 2018 в 05:33

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

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

  1. Подход Python
  2. find + bash подход
  3. подход, основанный только на bash с 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 и команды -exec

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, имя оболочки, поэтому оно не имеет значения, но важно "{}". Это цитируемый placeholder для имени файла, который find будет передан как аргумент bash.

С внутренней стороны команды 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 и glob

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

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
ответ дан 6 August 2018 в 22:40

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

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

  1. Подход Python
  2. find + bash подход
  3. подход, основанный только на bash с 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 и команды -exec

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, имя оболочки, поэтому оно не имеет значения, но важно "{}". Это цитируемый placeholder для имени файла, который find будет передан как аргумент bash.

С внутренней стороны команды 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 и glob

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

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
ответ дан 9 August 2018 в 03:06

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

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

  1. Подход Python
  2. find + bash подход
  3. подход, основанный только на bash с 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 и команды -exec

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, имя оболочки, поэтому оно не имеет значения, но важно "{}". Это цитируемый placeholder для имени файла, который find будет передан как аргумент bash.

С внутренней стороны команды 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 и glob

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

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
ответ дан 14 August 2018 в 21:24

Учитывая

$ 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
ответ дан 22 May 2018 в 23:54
  • 1
    Я не знаю, как работает эта команда, вы можете сделать ее немного универсальной (работать в любой папке) и объяснить, как ее использовать в практической ситуации. – Sumeet Deshmukh 7 April 2017 в 15:55

Учитывая

$ 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
ответ дан 18 July 2018 в 15:23

Учитывая

$ 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
ответ дан 24 July 2018 в 20:37
  • 1
    Я не знаю, как работает эта команда, вы можете сделать ее немного универсальной (работать в любой папке) и объяснить, как ее использовать в практической ситуации. – Sumeet Deshmukh 7 April 2017 в 15:55

Учитывая

$ 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
ответ дан 31 July 2018 в 23:39
  • 1
    Я не знаю, как работает эта команда, вы можете сделать ее немного универсальной (работать в любой папке) и объяснить, как ее использовать в практической ситуации. – Sumeet Deshmukh 7 April 2017 в 15:55

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

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