список файлов, пронумерованных в определенном диапазоне

28702
milkypostman

У меня есть набор файлов в каталоге, пронумерованных следующим образом:

file1.txt file2.txt ... file30.txt ... 

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

До сих пор я использовал следующие способы,

три аргумента

command file1[8-9].txt file2[0-9].txt file3[0-1].txt 

Теперь предположим, что я хочу любой номер,

петля

for i in `jot - 18 31 2`; do echo file$.txt; done | xargs command 

кажется, что это более надежный цикл (пробелы работают)

for i in `jot - 18 31 2`; do echo "\"file$.txt\" "; done | xargs command 

но кажется, что должен быть более простой способ сделать это. Я предполагаю, что лучшее решение - создать функцию bash, которая будет возвращать набор файлов в командную строку. Тогда я мог бы сделать что-то вроде,

command `filerange file 18 31` 

Есть ли лучшие способы или предложения по эффективному выполнению этой задачи?

Я заранее прошу прощения, если я пропустил тот же вопрос, на который ответили где-то еще в Интернете или на superuser.

15
Я обновил свой вопрос, включив в него решение, использующее цикл `for`, который позволяет использовать пробелы в именах файлов с использованием xargs. Кажется, это работает, если у вас нет bash 4. Если у вас есть bash 4, то обязательно используйте расширение скобки! ** См выбранный ответ. ** [Бесстыдный плагин для обновления Snow Leopard bash] (http://milkbox.net/brain/brace_completion_snow_leopard_upgrading_bash/) milkypostman 13 лет назад 0

1 ответ на вопрос

23
Dennis Williamson

Попробуй это:

for file in file.txt 

Он известен как «выражение последовательности» и является частью функции расширения скобок Bash . Работает в Баш 3 и 4.

Функция приращения является новой для Bash 4. Возможно, у вас есть Bash 3.x.

В Bash 4 вы можете сделать:

$ for i in ; do echo $i; done 1 3 5 

Но в Bash 3 вы должны сделать это, чтобы получить те же результаты:

$ for ((i=1; i<=6; i+=2)); do echo $i; done 

Та же форма увеличивается на единицу:

$ for ((i=1; i<=6; i++)); do echo $i; done 

Любое число может быть переменной или выражением. Однако в выражении последовательности числа должны быть константами

Вот пример использования этой формы в ваших файлах:

for ((i=18; i<=31; i++)) do echo "file$.txt" done 

Еще одна новая особенность выражений последовательностей в Bash 4 - возможность включать ведущие нули. Это полезно, если вы хотите создать (и использовать) пронумерованные файлы, которые можно правильно отсортировать.

В Bash 4:

touch file.txt 

создаст файлы с именами «file001.txt» - «file010.txt». Их имена будут отсортированы в ожидаемом порядке. Без начальных нулей, file10.txt будет отсортирован перед file1.txt.

Для работы с файлами вы можете использовать тот же синтаксис начального нуля:

for file in file.txt; do echo "$file"; done 

В Bash 3, если вам нужны начальные нули, вам нужно добавить значение самостоятельно:

for i in  do printf -v i '%03d' $i  echo "file$.txt" done 

Оператор printfдобавляет к значению i начальные нули, поэтому ширина равна 3, например («4» становится «004»).

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

Аранжировать пробелы в именах файлов просто:

$ touch "space name "" more spaces" $ ls -l sp* -rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000008 more spaces -rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000011 more spaces -rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000014 more spaces -rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000017 more spaces $ for f in "space name "" more spaces"; do mv "$f" "$.txt"; done $ ls -l sp* -rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000008 more spaces.txt -rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000011 more spaces.txt -rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000014 more spaces.txt -rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000017 more spaces.txt 
Благодарю вас! Я не знаю, где это было всю мою жизнь. Единственная вещь, которую я не могу заставить работать - это то, что приращение не работает в OSX-версии bash. то есть я не могу заставить `` работать в моем OSX bash. milkypostman 13 лет назад 0
Ну, это потому, что Snow Leopard (по какой-то причине) использует bash 3.1. Это проблема программного обеспечения. milkypostman 13 лет назад 0
@milkypostman: функция приращения и начальные нули `` являются новыми для Bash 4. Возможно, у вас есть Bash 3.x. Если вам нужна функция приращения или для использования переменных для границ диапазона, используйте эту форму: `for ((i = 1; i <= 10; i + = 2}` (или `i ++` для увеличения на единицу). Любой числа могут быть переменными или выражениями. Затем, чтобы использовать значение внутри цикла `for`:` echo "file $ .txt". В Bash 3, если вам нужны ведущие нули, внутри цикла for: `printf -vi '% 03d' $ i`, который добавит значение` i` к начальным нулям, например, к ширине, равной 3 ("4" становится "004"). Dennis Williamson 13 лет назад 0
Деннис, есть ли способ обновить свое решение, включив альтернативную форму. Будучи комментарием, это немного запутывает то, что я, вероятно, должен получить. milkypostman 13 лет назад 0
@milkypostman: Смотрите мой отредактированный ответ. Dennis Williamson 13 лет назад 0
Я бы только добавил еще один комментарий. Методы, которые вы указали выше с использованием `echo`, будут работать до тех пор, пока в вашем имени файла нет пробелов. В этот момент они ломаются. У меня была эта проблема в прошлом, но я избегаю файлов с пробелами любой ценой. Просто предупреждение и почему расширение скобок так приятно. Вместо того, чтобы больше облажаться с этим для дерьмового цикла, я пошел дальше и установил новую версию bash для OSX [вот как вы это делаете, если другим любопытно] (http://milkbox.net/brain/brace_completion_snow_leopard_upgrading_bash/) milkypostman 13 лет назад 0
@milkypostman: действительно легко разместить пробелы в циклах, как я их показал. Смотрите мое дополнительное редактирование. Ключ должен заключить в кавычки переменную. Dennis Williamson 13 лет назад 0