Предполагает, что удар и GNU находят.
mv_preserve_structure() {
local src_file="$1"
local dest="$2"
local rel_dir="$(dirname "$src_file")/"
rel_dir="${rel_dir#*/}" # returns "2/3" if rel_dir was "src/2/3"
mkdir -p "$dest/$rel_dir"
mv "$src_file" "$dest/$rel_dir"
}
# unlike mv, this requires the destination dir as the first parameter
mv_dirs() {
local dest="$1"
shift
for dir in "$@"; do
for filename in "$dir"/*; do
[[ -f "$filename" ]] && mv_preserve_structure "$filename" "$dest"
done
done
}
mv_dirs dst src src/1 src/2/3
Решение @l0b0 переписывается для лучшей устойчивости:
printf '%s\0' index-*.txt |
sort --zero-terminated --field-separator - --key 2rn |
xargs -0r rename --verbose '
s/^index-([0-9]+)\.txt$/$1/;
$_="index-" . ($_ + 1) . ".txt"'
Не стесняйтесь включать в свое решение, и я удалю свой ответ позже.
Обратите внимание, что это и решения @l0bo - конкретный GNU, не Unix (GNU Не Unix).
Существует немного известной стандартной команды на Unix, который может помочь нам здесь найти общее решение в нахождении, в котором порядке серия переименовывает, должны быть сделаны: tsort
Скажите, что у нас есть список, переименовывает, чтобы быть сделанным в названном файле renames.txt
(принимающий ради демонстрации, что их имя не содержит пробелы):
d a
e f
b e
a c
Поскольку d
должен быть переименован к a
, это означает a
должен быть переименован прежде d
. Таким образом, у нас есть частичный порядок сортировки там, который был бы реверсом порядка, файлы должны быть переименованы.
tsort
инструмент должен вывести полный порядок сортировки из списка частичных порядков сортировки. Это возвратилось бы с ошибкой, если бы был цикл, который помог бы нам обнаружить случаи, где нет никакого решения. Если мы подаем заявку tsort
на том входе это дает нам:
b
d
e
a
f
c
Который говорит b
должен быть переименован после d
после e
. Мы можем использовать GNU tac
(некоторые системы также имеют tail -r
) инвертировать тот порядок:
c
f
a
e
d
b
И присоединитесь, это с нашим списком переименовывает:
tsort renames.txt | tac | awk '
NR==FNR {
ren[$1] = $2
next
}
$1 in ren {
print "mv -i --", $1, ren[$1]
}' renames.txt -
который дает нам:
mv -i -- a c
mv -i -- e f
mv -i -- d a
mv -i -- b e
к которому мы можем затем передать по каналу sh
выполниться.
Обратите внимание однако, что вышеупомянутый код не устойчив в этом, мы не проверяли статус выхода tsort
выше для обнаружения циклов и имен файлов не должен содержать специальные символы оболочки.
robustification оставляют как осуществление читателю ;-)
Это работает на конкретный случай выше:
rename --verbose 's/^index-([0-9]+)\.txt$/$1/; $_="index-" . ($_ + 1) . ".txt"' $(printf '%s\n' index-*.txt | sort --field-separator - --key 2n | tac)
Но:
Не прямой ответ на Ваш вопрос, поскольку Вы упоминаете удар, но с zsh, можно указать порядок сортировки и числовой вид с globbing спецификаторами.
$ echo index-*.txt
index-12.txt index-1.txt index-2.txt index-4.txt
$ echo index-*.txt(n)
index-1.txt index-2.txt index-4.txt index-12.txt
$ echo index-*.txt(nOn)
index-12.txt index-4.txt index-2.txt index-1.txt
Или можно определить собственный порядок сортировки с функцией и использованием index-*(o+that-function)
.
Также обратите внимание, что zsh имеет свое собственное rename
встроенная функция вызвана zmv
:
$ zmv -fvQ 'index-(<->).txt(n)' 'index-$(($1-1)).txt'
mv -- index-1.txt index-0.txt
mv -- index-2.txt index-1.txt
mv -- index-4.txt index-3.txt
mv -- index-12.txt index-11.txt
$ zmv -fvQ 'index-(<->).txt(nOn)' 'index-$(($1+1)).txt'
mv -- index-11.txt index-12.txt
mv -- index-3.txt index-4.txt
mv -- index-1.txt index-2.txt
mv -- index-0.txt index-1.txt
Для контекста я использую приложение LapseIt Pro для замедленной съемки, и по какой-то причине оно остановилось, затем я перезапустил замедленную съемку, но присвоил ему другое имя проекта, например:-
Proj10 _img0000000x
Мне нужно было переименовать все 3000-ые файлы в предыдущий проект Proj9 _img0000000x и изменить номер в конце, чтобы проект имел непрерывную подачу имени + номера, чтобы я мог отображать все изображения, например, как одно видео проекта
Proj10 _img00000001 --> Proj10 _img00003249 необходимо изменить на Proj9 _img00004325 --> Proj9 _img00007574
В итоге конечный результат выглядит так в папке проекта Proj9 _img00000001 --> Proj9 _img00007574
Если вы используете Mac OSX (я использую Mojave ), вы можете
Я все еще рассматриваю команды командной строки grep/sed/awk/cut & find, но пока описанный выше метод работает (Мне нужно было сделать видео как можно скорее для публикации)
--
параметр в конце и настраивают regex, на который он на самом деле работает$'--$`!*@\a\b\E\f\r\t\v\\\'"\360\240\202\211-'{1,2,3,4,5,6,7,8,9,10,11}$'\n'
– l0b0 24.09.2012, 17:55