У меня такая структура каталогов:
Bookname Edition 1
Bookname Edition 1 type1.pdf
Bookname Edition 1 type2.pdf
Bookname Edition 2
Bookname Edition 2 type1.pdf
Bookname Edition 2 type2.pdf
Я хочу рекурсивно изменить имя из Edition в Volume каталога и имена файлов в этих каталогах.
Я начал с этого, и это нормально, если я в каталоге:
for f in *.pdf; do
a="$(echo $f | sed s/Edition/Volume/)"
mv "$f" "$a"
done
Затем я попробовал это, чтобы изменить все файлы под каталогами, и вот тогда я застрял ...
Пожалуйста, расскажите, как это сделать или дайте мне лучший способ сделать это. В 100 каталогах имеется 15000 PDF-файлов.
Если ваша структура имеет только два уровня, вам не нужно использовать рекурсию.
Не разбирайте имена файлов с помощью sed. Если вы хотите использовать синтаксис стиля regex и sed для переименования файлов, используйте rename. Если вы используете Ubuntu 17.10, вам необходимо установить его
sudo apt install rename
. Затем вы можете использовать ответ pa4080.
С помощью rename используйте параметр -n для тестирования .
rename -n 'expression' file(s)
Вы также можете просто использовать команду mv. В качестве однострочной команды:
for d in ./*/; do mv -v "$d" "${d/Edition/Volume}"; done; for f in ./*/*; do mv -v "$f" "${f/Edition/Volume}"; done
Вы можете использовать echo для тестирования с помощью mv, то есть echo mv -v source dest, но здесь приводятся неточные результаты, если вы не проверите и не запустите циклы отдельно.
Как сценарий:
#!/bin/bash
# rename directories first
for d in ./*/; do
mv -v "$d" "${d/Edition/Volume}"
done
# now rename files
for f in ./*/*; do
mv -v "$f" "${f/Edition/Volume}"
done
mv и rename распознают --, чтобы указать конец опций. Поскольку в этом примере все пути начинаются с ./, нам не нужно использовать это, но если пути могут начинаться с -, используйте -- в конце опций, например rename -n -- 's/foo/bar/' *, чтобы предотвратить эти пути интерпретируются как опции.
Если ваша структура имеет только два уровня, вам не нужно использовать рекурсию.
Не разбирайте имена файлов с помощью sed. Если вы хотите использовать синтаксис стиля regex и sed для переименования файлов, используйте rename. Если вы используете Ubuntu 17.10, вам необходимо установить его
sudo apt install rename
. Затем вы можете использовать ответ pa4080.
С помощью rename используйте параметр -n для тестирования .
rename -n 'expression' file(s)
Вы также можете просто использовать команду mv. В качестве однострочной команды:
for d in ./*/; do mv -v "$d" "${d/Edition/Volume}"; done; for f in ./*/*; do mv -v "$f" "${f/Edition/Volume}"; done
Вы можете использовать echo для тестирования с помощью mv, то есть echo mv -v source dest, но здесь приводятся неточные результаты, если вы не проверите и не запустите циклы отдельно.
Как сценарий:
#!/bin/bash
# rename directories first
for d in ./*/; do
mv -v "$d" "${d/Edition/Volume}"
done
# now rename files
for f in ./*/*; do
mv -v "$f" "${f/Edition/Volume}"
done
mv и rename распознают --, чтобы указать конец опций. Поскольку в этом примере все пути начинаются с ./, нам не нужно использовать это, но если пути могут начинаться с -, используйте -- в конце опций, например rename -n -- 's/foo/bar/' *, чтобы предотвратить эти пути интерпретируются как опции.
Если ваша структура имеет только два уровня, вам не нужно использовать рекурсию.
Не разбирайте имена файлов с помощью sed. Если вы хотите использовать синтаксис стиля regex и sed для переименования файлов, используйте rename. Если вы используете Ubuntu 17.10, вам необходимо установить его
sudo apt install rename
. Затем вы можете использовать ответ pa4080.
С помощью rename используйте параметр -n для тестирования .
rename -n 'expression' file(s)
Вы также можете просто использовать команду mv. В качестве однострочной команды:
for d in ./*/; do mv -v "$d" "${d/Edition/Volume}"; done; for f in ./*/*; do mv -v "$f" "${f/Edition/Volume}"; done
Вы можете использовать echo для тестирования с помощью mv, то есть echo mv -v source dest, но здесь приводятся неточные результаты, если вы не проверите и не запустите циклы отдельно.
Как сценарий:
#!/bin/bash
# rename directories first
for d in ./*/; do
mv -v "$d" "${d/Edition/Volume}"
done
# now rename files
for f in ./*/*; do
mv -v "$f" "${f/Edition/Volume}"
done
mv и rename распознают --, чтобы указать конец опций. Поскольку в этом примере все пути начинаются с ./, нам не нужно использовать это, но если пути могут начинаться с -, используйте -- в конце опций, например rename -n -- 's/foo/bar/' *, чтобы предотвратить эти пути интерпретируются как опции.
Вы можете использовать команду rename два раза для выполнения этой задачи:
rename 's/Edition/Volume/' */ # rename the directories
rename 's/Edition/Volume/' */*.pdf # rename the PDF files inside
Вот два похожих вопроса:
Рекурсивный bash script Объяснение скрипта оболочки для рекурсивной печати полного дерева каталоговВ многоуровневых каталогах вы можете сделать это за один шаг, но проблема в том, что вам нужно переименовать каталоги снизу вверх, чтобы команда или сценарий не изменили имя каталога до его содержимого изменяется.
В python вы можете использовать:
os.walk
в сочетании с
topdown=False
В сценарии:
#!/usr/bin/env python3
import os
import shutil
import sys
for root, dirs, files in os.walk(sys.argv[1], topdown=False):
for f in files:
shutil.move(
root+"/"+f, root+"/"+f.replace("Edition", "Volume").strip()
)
for dr in dirs:
shutil.move(
root+"/"+dr, root+"/"+dr.replace("Edition", "Volume").strip()
)
[d4 ] Сохраните сценарий как change_name.py, запустите его с каталогом как аргумент: python3 /path/to/change_name.py <directory>
Это работает рекурсивно на любом количестве уровней.
Используйте find с опцией -depth в сочетании с prename:
find [DIRS...] -depth | prename -n 's|Edition(?=[^/]*$)|Volume|'
Объяснение:
-depth выбирает дочерние элементы каталогов перед родителями. Инструмент, «потребляющий» выбранные имена путей для переименования, может затем переименовать детей перед родителями. s|Edition(?=[^/]*$)|Volume| заменяет первое вхождение Edition в имени пути с помощью Volume, но только если остаток не содержит /, i. е. он применяется только к последнему компоненту имени пути (достигается положительным внешним ожиданием (?=[^/]*$)). -n сообщает prename, что фактически не переименовывает пути, а печатает, как он их переименовал. Удалите эту опцию, чтобы на самом деле переименовать их.Используйте find с опцией -depth в сочетании с prename:
find [DIRS...] -depth | prename -n 's|Edition(?=[^/]*$)|Volume|'
Объяснение:
-depth выбирает дочерние элементы каталогов перед родителями. Инструмент, «потребляющий» выбранные имена путей для переименования, может затем переименовать детей перед родителями. s|Edition(?=[^/]*$)|Volume| заменяет первое вхождение Edition в имени пути с помощью Volume, но только если остаток не содержит /, i. е. он применяется только к последнему компоненту имени пути (достигается положительным внешним ожиданием (?=[^/]*$)). -n сообщает prename, что фактически не переименовывает пути, а печатает, как он их переименовал. Удалите эту опцию, чтобы на самом деле переименовать их.В многоуровневых каталогах вы можете сделать это за один шаг, но проблема в том, что вам нужно переименовать каталоги снизу вверх, чтобы команда или сценарий не изменили имя каталога до его содержимого изменяется.
В python вы можете использовать:
os.walk
в сочетании с
topdown=False
В сценарии:
#!/usr/bin/env python3
import os
import shutil
import sys
for root, dirs, files in os.walk(sys.argv[1], topdown=False):
for f in files:
shutil.move(
root+"/"+f, root+"/"+f.replace("Edition", "Volume").strip()
)
for dr in dirs:
shutil.move(
root+"/"+dr, root+"/"+dr.replace("Edition", "Volume").strip()
)
Сохраните сценарий как change_name.py, запустите его с каталогом как аргумент:
python3 /path/to/change_name.py <directory>
Это работает рекурсивно на любом количестве уровней.
Вы можете использовать команду rename два раза для выполнения этой задачи:
rename 's/Edition/Volume/' */ # rename the directories
rename 's/Edition/Volume/' */*.pdf # rename the PDF files inside
Вот два похожих вопроса:
Рекурсивный bash script Объяснение скрипта оболочки для рекурсивной печати полного дерева каталоговИспользуйте find с опцией -depth в сочетании с prename:
find [DIRS...] -depth | prename -n 's|Edition(?=[^/]*$)|Volume|'
Объяснение:
-depth выбирает дочерние элементы каталогов перед родителями. Инструмент, «потребляющий» выбранные имена путей для переименования, может затем переименовать детей перед родителями. s|Edition(?=[^/]*$)|Volume| заменяет первое вхождение Edition в имени пути с помощью Volume, но только если остаток не содержит /, i. е. он применяется только к последнему компоненту имени пути (достигается положительным внешним ожиданием (?=[^/]*$)). -n сообщает prename, что фактически не переименовывает пути, а печатает, как он их переименовал. Удалите эту опцию, чтобы на самом деле переименовать их.В многоуровневых каталогах вы можете сделать это за один шаг, но проблема в том, что вам нужно переименовать каталоги снизу вверх, чтобы команда или сценарий не изменили имя каталога до его содержимого изменяется.
В python вы можете использовать:
os.walk
в сочетании с
topdown=False
В сценарии:
#!/usr/bin/env python3
import os
import shutil
import sys
for root, dirs, files in os.walk(sys.argv[1], topdown=False):
for f in files:
shutil.move(
root+"/"+f, root+"/"+f.replace("Edition", "Volume").strip()
)
for dr in dirs:
shutil.move(
root+"/"+dr, root+"/"+dr.replace("Edition", "Volume").strip()
)
Сохраните сценарий как change_name.py, запустите его с каталогом как аргумент:
python3 /path/to/change_name.py <directory>
Это работает рекурсивно на любом количестве уровней.
Вы можете использовать команду rename два раза для выполнения этой задачи:
rename 's/Edition/Volume/' */ # rename the directories
rename 's/Edition/Volume/' */*.pdf # rename the PDF files inside
Вот два похожих вопроса:
Рекурсивный bash script Объяснение скрипта оболочки для рекурсивной печати полного дерева каталогов