Как удалить пронумерованные файлы в заданном диапазоне?

11

У меня есть folderA , у которого есть некоторые файлы с числовой последовательностью, начиная с a_000000 . Я хочу, чтобы удалить файлы, начиная с определенного номера: предположим, что a_000750 до конца файлов в этом folderA . Может ли кто-нибудь посоветовать, как это сделать, используя сценарий оболочки?

    
задан Tak 27.09.2014 в 14:22
источник

3 ответа

24

Предполагая, что вы знаете или можете угадать конец диапазона, вы можете использовать расширения расширений :

rm a_{000750..000850}

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

find . -name 'a_*' | while read file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

Здесь find просто перечисляет все файлы, соответствующие a_* . Список передается в цикл while , где каждое имя файла считывается в переменной $file . Затем, используя bash's функции обработки строк , если числовая часть (поиск печатает файлы как ./file , поэтому ${file#./a_} печатает только число) 000750 или больше, файл удален. -v находится там, чтобы вы могли видеть, какие файлы были удалены.

Обратите внимание, что вышеприведенное предполагает имена файлов. Если ваши имена могут иметь пробелы, символы новой строки или другие странные символы, используйте это вместо:

find . -name 'a_*' -print0 | while IFS= read -rd '' file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done
    
ответ дан terdon 27.09.2014 в 15:00
источник
3

Вы можете сделать что-то вроде этого:

find . -regextype posix-extended -iregex './a_[0-9]{6}' -execdir bash -c '[[ ${1##./a_} > 000750 ]] && echo $1' "removing: " {} \;

Или:

find . -regextype posix-extended -iregex './a_[0-9]{6}' | sort | sed '0,/000750/d' | xargs echo

Первый метод предполагает фиксированный префикс, отключает его и проверяет значение.

Второй метод предполагает суффикс фиксированной длины (и общий фиксированный префикс) и полагается на этот факт; и что, в то время как 201 приходит до 31 в лексикографическом режиме, это не до 031 .

Проверьте это с помощью команды echo , и как только вы убедитесь, что она содержит список правильных файлов, вместо этого используйте rm .

    
ответ дан muru 27.09.2014 в 14:33
0

Решение оболочки POSIX

первое решение terdon зависит от расширения брекетов, которое является свойством bash и ksh , однако это не может использоваться в стандартной оболочке /bin/sh , которая на Ubuntu символически связана с /bin/dash .

В случаях, когда вам нужно полагаться на /bin/sh для переносимости ваших скриптов, есть два способа приблизиться к этому. Один из них был бы через глобус. Просто cd folderA и оттуда выполните rm a_* . Другим способом было бы реализовать альтернативу C-style для цикла с использованием while <CONDITION>;do ...done в языке оболочки и форматировать числа с printf :

$ sh -c 'i=0;while [ $i -le 750 ]; do filename=$(printf "a_%06d" $i);echo "$filename";i=$((i+1)) ;done'

Обратите внимание, что здесь я использую echo . Замените echo "$filename" rm ./"$filename" или rm -- "$filename" , когда вы будете готовы удалить файлы. Также обратите внимание, что это должно быть выполнено, когда вы уже cd ed в нужную директорию.

(ab) с помощью awk

Awk, являющийся приятным C-подобным языком, может помочь нам двумя способами: (1) мы можем генерировать имена файлов с помощью for-loop и форматировать их с помощью функции sprintf и (2) удалять указанные файлы с помощью команды system() , который передаст наше сгенерированное имя файла и rm команды /bin/sh :

awk 'BEGIN{for(i=0;i<=750;i++){filename=sprintf("a_%06d",i);system("rm "filename);} }'

Perl

Продолжая идею портативного подхода, когда мы «генерируем» имена файлов, мы можем сделать то же самое в Perl:

perl -le 'for(0..750){$fd=sprintf("a_%06d",$_);unlink($fd)}'
    
ответ дан Sergiy Kolodyazhnyy 18.11.2017 в 18:17