Разделите имена файлов и переименуйте

Используйте -exec опция объединить обоих команды, которые работают на Вас:

find . ! -name . -prune ! -type d -exec ls -gohU {} +
6
18.04.2015, 15:23
4 ответа

Вам не нужен Rename Команда для этого, вы можете сделать это непосредственно в оболочке:

c=0; for i in *; do let c++; mv "$i" "gg_$(printf "%03d" $c)${i#"${i%.*}"}"; done

printf "% 03D" $ C будет распечатать переменную $ C , прокладывая его с 3 ведущими 0s по мере необходимости. Пусть C ++ увеличивает счетчик ( $ C ). $ {I # '$ {i%. *} "} извлекает расширение. Больше на этом здесь .

Я бы не использовал Rename для этого. Я не думаю, что это может сделать расчеты. Действительные конструкции Perl, такие как S /.*/$ C ++ / E , и я не вижу какой-либо другой способ, чтобы он сделал расчеты. Это означает, что вам все равно нужно будет запустить его в петле и иметь что-то еще, увеличивайте счетчик для вас. Что-то вроде:

c=0;for i in *; do let c++; rename -n 's/.*\.(.*)/'$c'.$1/' "$i"; done

, но нет никакого преимущества по сравнению с более простым MV .

6
27.01.2020, 20:23

Этот работал для меня. (Но команда Rename используется здесь Perl Rename ).

ls -1 -c | xargs rename -n 's/.*/our $i; sprintf("gg%04d", $i++)/e'

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

Тем не менее, поскольку он разрывается, когда есть пробелы на именах файлов, давайте попробуем исправить вышеуказанные проблемы.

find -print0 | xargs -0 rename 's/.*/our $i; sprintf("gg%04d", $i++)/e'

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

Чтобы исправить эту проблему, мы могли бы перефразировать нашу команду, поскольку @terdon предлагает в его комментариях. Окончательная модифицированная команда выглядит как

find -maxdepth 1 -type f -print0 | xargs -0 rename 's/.*/our $i; sprintf("gg%04d", $i++)/e'

тестирование

У меня есть следующие файлы в моей папке. Не переименовывает меня - это подпункта, который мы не хотим переименовать.

ls
Don't rename me  file1  file with spaces  hello

Теперь я выполняю команду, и я получаю ниже вывод.

find -maxdepth 1 -type f -print0 | xargs -0 rename -n 's/.*/our $i; sprintf("gg%04d", $i++)/e'
./file1 renamed as gg0000
./hello renamed as gg0001
./file with spaces renamed as gg0002

Флаг -N --n может быть удален, если мы удовлетворены тем, что мы видим как окончательный выход.

Ссылки

https://stackoverflow.com/a/23207377/1742825

2
27.01.2020, 20:23

При условии отсутствия в именах файлов одинарных кавычек ' можно сделать так:

i=0; set --
for f in *
do set -- "$@" "$f" gg "$((i+=1))" "${f#"${f%.*}"}"
done
printf "mv '%s' '%s%03d%s'\n" "$@" | sh

Таким образом, если имя файла содержит . , то оно и все, что за ним следует, сохраняется, в противном случае это поле пустое, а printf там ничего не печатает.

Я полагаю, что даже если в именах файлов есть одинарные кавычки, то можно сделать...

i=0; set --
for f in *
do set -- "$@" "$((i+=1))" gg "$i" "$i#\"\${$i%.*}\""
done
printf 'mv "${%d}" "%s%03d${%s}"\n' "$@" | sh -s -- *

... что, вероятно, гораздо безопаснее в целом.

Но знаете, подумав об этом, я пришел к выводу, что и то, и другое - это слишком много работы. Единственная причина, по которой я пробиваю оба списка, это чтобы избежать проверки на нулевой подкладке. Я предпочитаю строить список в одной подоболочке и передавать его с помощью одной write() в другую подоболочку, когда это необходимо.

Но при этом нулевая подложка не может быть слишком сложной. Я немного поработал с ним и придумал это маленькое математическое утверждение:

$((z/=(m*=((i+=1)<$m?1:10))/$m))

Если поместить его в итерационный цикл, то он увеличит $i один раз на элемент, повысит множитель $m на экспоненциальный отсчет для каждого из десяти факторов, и десятину $z для каждого из них. Идея состоит в том, чтобы получить значение в $z до начала цикла, который удерживает наибольший возможный прирост $i. Это просто делается:

set -- *; max=$# z=1
until [ "${#z}" -gt "${#max}" ]; do : "$((z*=10))"; done

Это полностью автоматизированный способ - он автоматически подпишет любое максимальное число, которое может быть увеличено. Но, честно говоря, $z просто должно быть числом, начинающимся с 1, за которым следуют только нули, так что:

set -- *; z=1000

... будет падом к полю тысяч. Во всяком случае, вот небольшая демонстрация, которую я использовал при тестировании:

time dash <<\CMD
    str=100000 z=1 m=1 i=0 
    until [ "${#z}" -gt "${#str}" ]; do : "$((z*=10))"; done
    while : "$((z/=(m*=((i+=1)<$m?1:10))/$m))" &&
    case "$i" in (*[2-8]*|*9*[10]*|*1*[19]*) continue;;
    ([019]*) set -- "$@" "z: $z m: $m i: $i" "${z#?}$i";;esac
    do [ "$i" = "$str" ] && printf %s\\n "$@" && break; done
CMD

Большая часть - это фильтрация вывода, потому что я хотел быть уверен, что она будет продолжать работать при большом количестве элементов, но я не хотел читать 100000 результатов.

OUTPUT

z: 100000 m: 10 i: 1
000001
z: 100000 m: 10 i: 9
000009
z: 10000 m: 100 i: 10
000010
z: 10000 m: 100 i: 99
000099
z: 1000 m: 1000 i: 100
000100
z: 1000 m: 1000 i: 999
000999
z: 100 m: 10000 i: 1000
001000
z: 100 m: 10000 i: 9999
009999
z: 10 m: 100000 i: 10000
010000
z: 10 m: 100000 i: 99999
099999
z: 1 m: 1000000 i: 100000
100000
dash <<<''  0.32s user 0.00s system 99% cpu 0.320 total

$m нужно инициализировать до первой стадии, на которой вы хотите, чтобы начали снимать лидирующие нули - я только что сделал m=1 выше. $z, как уже упоминалось, хранит верхний порядок величины. А $i считает петли, так что i=0, скорее всего, это безопасная ставка. В любом случае, остальное просто случается. Идея в том, чтобы снять лидирующую 1 из $z и прикрепить ее куда угодно.

set -- $(seq 1000); m=1 i=0 z=10000
while [ "$#" -gt 0 ] && : "$((z/=(m*=((i+=1)<$m?1:10))/$m))"
do printf 'mv "%s" "lead_string_%s"\n' "$1" "${z#1}$i${1#"${1%.*}"}"
shift; done

Я использую printf там только для того, чтобы показать, как это выглядит, хотя, конечно, весь смысл в том, чтобы избежать распечатки данных и вместо этого передать их в текущую оболочку в качестве подготовленного, разделенного аргумента. В любом случае, это выглядит как:

mv "1" "lead_string_0001"
mv "2" "lead_string_0002"
mv "3" "lead_string_0003"
...
mv "9" "lead_string_0009"
mv "10" "lead_string_0010"
mv "11" "lead_string_0011"
...
mv "15" "lead_string_0015"
...
mv "96" "lead_string_0096"
...
mv "99" "lead_string_0099"
mv "100" "lead_string_0100"
mv "101" "lead_string_0101"
mv "102" "lead_string_0102"
...
mv "998" "lead_string_0998"
mv "999" "lead_string_0999"
mv "1000" "lead_string_1000"

И не имеет значения, является ли это for или while loop you use. Так что с файлами можно просто сделать:

m=1 i=0 z=10000
for f in *; do : "$((z/=(m*=((i+=1)<$m?1:10))/$m))"
mv -- "$f" "lead_string_${z#1}$i${f#"${f%.*}"}"
done
3
27.01.2020, 20:23

Единственные номера дескрипторов файлов, которые можно использовать в сценарии оболочки, от 0 до 9 (т.е. одна цифра). Кавычка POSIX :

Открытые файлы представлены десятичными числами, начинающимися с нуля. Наибольшее возможное значение имеет реализация; однако все реализации должны поддерживать по меньшей мере от 0 до 9 включительно для использования приложением. Эти номера называются «дескрипторами файлов». (…) Операторам перенаправления может предшествовать одна или несколько цифр (без использования < пустых > символов) для обозначения номера дескриптора файла.

В грамматике ясно, что перед оператором перенаправления может быть несколько цифр. Однако в большинстве оболочек номер перед оператором анализируется только как дескриптор файла, если он состоит из одной цифры. Например, согласно спецификации POSIX, echo 10 > a должен либо перенаправить дескриптор файла 10 на a и создать пустой файл, либо выйти из строя, поскольку оболочка не поддерживает 10 как номер дескриптора файла. Ошибка также может быть вызвана тем, что номер дескриптора файла превышает предельное количество открытых файлов в процессе.

Но на практике большинство оболочек разбирают это как эхо 10 > a , т.е. записывают 10 в a . Даже ATT ksh93 и posh несовместимы, как и dash, mksh и zsh:

$ ksh -c 'echo 10>a; wc -c a'
3 a
$ posh -c 'echo 10>a; wc -c a'
3 a

В Linux, я могу найти только bash и BusyBox пепел, которые соответствуют POSIX на этот пункт.

$ bash -c 'echo 10>a; wc -c a' 

0 a

Аналогично, (...) 200 > some-файл должен быть проанализирован как перенаправление и может работать или не работать в зависимости от того, поддерживает ли оболочка дескриптор файла с таким высоким значением. Но большинство оболочек вместо этого сообщают об ошибке синтаксиса, поскольку они разбирают часть 200 не как номер дескриптора файла, а как обычный маркер.

В связанной заметке, echo 01 > & 1 должны напечатать пустую строку, потому что 01 должны быть проанализированы как номер дескриптора файла, но снова только bash и BusyBox ash получают это право.

Таким образом, на практике в сценариях оболочки можно использовать только однозначные дескрипторы файлов . Дескрипторы 0, 1 и 2 имеют стандартное значение; дескрипторы 3-9 могут использоваться свободно. Снаряды не будут использовать fd 3-9 в своих внутренних целях. Независимо от выбранного дескриптора файла, возможно, что дескриптор файла уже открыт при запуске оболочки, но это не имеет значения: любое переназначение дескриптора файла в сценарии остается в сценарии и не влияет на родительский процесс сценария.

-121--84607-

строка одна из руководств по установке, связанных с состояниями

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

Незашифрованный процесс для разделов имеет эти разделы,"/" "/usr ""/tmp" "/home ""/var" "корневой раздел настроен на загрузку, но при шифровании раздела необходимо использовать незашифрованный загрузочный раздел, поскольку для расшифровки корневого раздела и других обычных разделов необходимо использовать незашифрованный загрузочный раздел для расшифровки корневого раздела.

Если не установить LVM для каждого раздела/usr/tmp и зашифровать его, установщик не поймет, что точки монтирования были набор и сбойны, в этом руководстве перечисляется шаг

https://dl.dropboxusercontent.com/u/40638984/how_to_lvm_debian_wheezy.pdf

-121--151071-

Просто приращение переменной при каждой итерации. Поскольку rename наборов используют строгие , необходимо использовать глобальную переменную $:: i (или использовать no strict , или объявить переменную с помощью our ).

rename 'our $i; s/.*/gg_$i/; ++$i' *

Если требуется заполнить число первыми нулями, подсчитайте количество файлов. Список файлов находится в @ ARGV .

rename 'our $i; my $width = length(scalar(@ARGV)); s/.*/sprintf("gg_%0${width}d", $i++)/e' *

Можно проверить, определена ли переменная счетчика для выполнения кода только на первой итерации.

rename 'our ($i, $width); if (!defined $width) {$width = length(scalar(@ARGV)); $i = 0;} s/.*/sprintf("gg_%0${width}d", $i++)/e' *

При передаче имен файлов с частью каталога (т.е. при передаче имен файлов, содержащих / - здесь не происходит с * ), измените s/. */.../ на s/[ ^/] *\z/.../.

1
27.01.2020, 20:23

Теги

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