Bash - перемещать/переименовывать файлы с числовой сортировкой, начиная с введенного номера и далее

попробуй

awk '$2 != 0 || $3 !=0 || $4 !=0 || $5 !=0 ' foo.txt

где

  • это отфильтрует (график )строку по крайней мере с ненулевым значением.
  • пожалуйста, awk не будет получать строки одну за другой, нет необходимости в течение некоторого времени.
  • также исходный файл не будет редактироваться.

Редактировать:

«полная противоположность» немного нечеткая, однако, чтобы понять

  • все последние поля равны 0, используйте$2 == 0 && $3 == 0 &&...(&&для логического и для awk, ||для логического или)
  • не менее 0 использований$2==0 || $3==0 ||...

если у вас много полей, чтобы строка была не нулевой:

awk 'NF>2 {for(i=2;i<=NF;i++) if ($i) {print ; next ;}}' file

где

  • NFномер поля
  • NF>2убедитесь, что в строке есть как минимум 2 поля, а цикл for завершается.
0
26.12.2019, 03:29
3 ответа

Это делает то, что вы хотите. Одна вещь :Я думаю, что это работает только в BASH. MAXDIGITSне является обязательным, я поместил его туда на случай, если вам нужно работать с тройными цифрами или более. Если вы не используете его, удалите соответствующие строки.

    #!/bin/bash

    BOTTOM=$1
    SHIFT=$2
    MAXDIGITS=0$3
    for filename in $(ls -r *.{txt,log}); do
        PREFIX=${filename%%_*}
        NEWPREFIX=$(expr $PREFIX + $SHIFT)
        if [ $PREFIX -ge $BOTTOM ]; then
            NEWPREFIX=$(printf %${MAXDIGITS}d $NEWPREFIX)
            mv $filename ${NEWPREFIX}_${filename#*_}
        fi
    done

Чтобы использовать:

   ./myscript <BOTTOM> <SHIFT> <MAXDIGITS>
    ### Example:
   ./miscript 03 02 2 #This means "Start at 03_filename.*, shift the prefixes by 2 and use 2 digits to construct the new prefixes".

Если у вас есть другие файлы в том же каталоге, которые не соответствуют тому же синтаксису (префикс _имя файла.{txt,log} ), вы должны отфильтровать их. Кроме того, я использовал «_», чтобы отделить префикс от имени файла, поэтому, если вы измените его, вам нужно будет исправить код.

1
28.01.2020, 02:29

Вот bashодин -вкладыш, который включает две подстановки процессов и очень простую awkпроцедуру:

$ ls -r -1 *_file_name.{txt,log}    # list initial files in reverse order
05_file_name.log
05_file_name.txt
04_file_name.log
03_file_name.txt
03_file_name.log
03_file_name.txt
02_file_name.log
02_file_name.txt
01_file_name.log
01_file_name.txt

$ source <(awk 'BEGIN{FS="_"} $1>2 {prefix=$1+2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}' <(ls -r -1 *_file_name.{log,txt}))

$ ls -1 *_file_name.{txt,log}     # list resulting files
01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
05_file_name.log
05_file_name.txt
06_file_name.log
06_file_name.txt
07_file_name.log
07_file_name.txt

Пояснение:

Одна строчка выше читается или, по крайней мере, «понятна» справа налево.

  • ls -r -1 *_file_name.{log,txt}перечисляет все файлы, подлежащие обработке, в обратном порядке, в формате одного столбца -.
    Обратите внимание, что если префиксы файлов (, обозначенные символом *), включают не числовые символы -, вы можете получить непредвиденные/нежелательные результаты. Чтобы этого не произошло, отфильтруйте файлы, которые будут обрабатываться на этом этапе.

  • <(...)замена процесса. Это позволяет ссылаться на предыдущий вывод результата с помощью дескриптора файла, то есть специального временного файла, называемого именованным каналом. Для получения подробной информации введите man bashв терминале.

  • awkсценарий:

    • BEGIN{FS="_"}перед началом обработки записей установите разделитель полей записи на " _" (1-й блок awk)
    • awkусловие второго блока,$1>2:обрабатывает только те записи, префикс имени файла которых строго больше 2
    • prefix=$1+2определяет внутреннюю переменную awk "prefix". Сделайте его численно равным префиксу $1+ 2
    • используйте printf("my_format",var1,var2,...)для вывода отформатированных команд, разделенных новой строкой. Обратите внимание, что форматирование включает в себя %0.2d, т. е. печать переменной «prefix» awkв виде двухзначного числа -с заполнением 0, когда это необходимо. Вывод:
      mv -f 05_file_name.log 07_file_name.log
      mv -f 05_file_name.txt 07_file_name.txt
      mv -f 04_file_name.log 06_file_name.log
      mv -f 04_file_name.txt 06_file_name.txt
      mv -f 03_file_name.log 05_file_name.log
      mv -f 03_file_name.txt 05_file_name.txt
  • обрабатывать этот отсортированный вывод как еще один файл (2-я замена процесса )и использовать его для выполнения команд mv -f....

Если вам интересно, почему неоднократное использование подстановки входящих или исходящих процессов(не соответствует POSIX ! )в bashвыгодно, см., например, это .

Последнее примечание:

Включение параметров среды выполнения в один из вышеописанных вкладышей -и инкапсуляция их в исполняемый сценарий оболочки не представляет труда, начиная с определения VAR1и VAR2путем присвоения процедуре awk:

$ source <(awk -v VAR1=2 -v VAR2=2 'BEGIN{FS="_"} $1>VAR1 {prefix=$1+VAR2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}' <(ls -r -1 *_file_name.{log,txt}))

А в исполняемом скриптеscript.sh:

$ cat script.sh
#!/usr/bin/bash
if [ "$#" -eq 2 ] ; then
    source  <(awk -v VAR1=$1 -v VAR2=$2 'BEGIN{FS="_"} $1>VAR1 {prefix=$1+VAR2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}' 
              <(ls -r -1 *_file_name.{log,txt})
             )
    exit 0
else
    echo "   Usage: script.sh VAR1 VAR2.\n    Abort execution (exit code 1)."
    exit 1
fi

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

Сценарий @MarceloCastro хорош, хотя он основан на цикле for, которого я стараюсь избегать, когда это возможно. forЦиклы, как правило, работают медленно, что можно заметить при обработке большого количества файлов.

1
28.01.2020, 02:29

Сzsh:

$ autoload zmv
$ zmv -n -f '(<3->)(_*)(#qnOn)' '${(l:2::0:)$(($1+2))}$2'
mv -- 05_file_name.txt 07_file_name.txt
mv -- 05_file_name.log 07_file_name.log
mv -- 04_file_name.txt 06_file_name.txt
mv -- 04_file_name.log 06_file_name.log
mv -- 03_file_name.txt 05_file_name.txt
mv -- 03_file_name.log 05_file_name.log

Затем снимите-n(для пробного -прогона ).

  • zmv pattern replacement:zmv— это автозагружаемая функция, которая использует мощные операторы zsh glob и расширения для сложного переименования файлов.
  • <x-y>сопоставляет десятичное число x и y.
  • (#q...)глобус квалификатор
  • nOn:nумерически oрдер (перевернутый с заглавной О )на nаме. Таким образом, 05...будет стоять перед 04...по мере необходимости, так как мы увеличиваем числа.
  • ${(l:n::padding:)expansion}:lef дополнить расширение до длины n с помощью заполнения . Таким образом, с ${(l:2::0:)}, левый блок до длины 2 с нулями.
  • $(($1+2)), первая захваченная группа увеличивается на 2.
  • $2:вторая группа захвата :что после ведущего числа.
0
28.01.2020, 02:29

Теги

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