Как пропустить первый элемент ls в цикле for

#bash #shell

#bash #оболочка

Вопрос:

Я выполняю команду, которая вводит список файлов в моей папке в качестве входных данных. Итак, я выполняю

 cat <(for i in ls *chr*.txt; do echo $i; done)
  

Однако я не хочу включать первую запись из этого списка. Другими словами, я хочу пропустить итерацию 1, поэтому у меня есть только n-1 *chr*.txt файлов. Как мне это сделать?

Комментарии:

1. Никогда не используйте ls таким образом. Смотрите синтаксический анализ

2. Обратите внимание, что echo $i это также ошибка — это искажает имена файлов, содержащие символы большого размера, пробелы и т.д. Всегда используйте echo "$i" или даже лучше printf '%sn' "$i" . Смотрите BashPitfalls #14 .

3. Пожалуйста, обратите внимание: Почему не выполнить синтаксический анализ ls ?

4. Звучит как XY . Дайте больше контекста. Что это за имя, которое вы пытаетесь пропустить? Бьюсь об заклад, мы сможем исправить это в глобусе.

Ответ №1:

ls Здесь вообще не используйте. Поместите ваши файлы в массив, и вы сможете расширить массив, начиная со второго элемента.

 files=( *chr*.txt )
printf '%sn' "${files[@]:1}"
  

В базовых оболочках POSIX, которые не поддерживают массивы, вы можете использовать "$@" для той же цели, shift удалив первый элемент:

 set -- *chr*.txt    # put all names matching the pattern in $1/$2/...
shift               # remove $1, putting $2 in its place, moving $3 to $2, etc
printf '%sn' "$@"  # print each item from our argument list on a separate line.
  

Комментарии:

1. @anubhava, хех, ты прав. Я тестировал с "$@" , но $0 это особый случай.

2. @MAPK, однострочники — плохая идея в bash. Помните, что это язык с почти 50-летним наследием обратной совместимости — обходить все значения по умолчанию, которые были установлены из-за неправильных решений, принятых людьми, внедрявшими оболочки-предшественники десятилетия назад, означает платить высокую цену за детализацию, чтобы добиться правильности. Вы всегда можете поместить ; между вашими двумя командами, если по какой-то причине вы действительно хотите, чтобы они были в одной строке.

Ответ №2:

Не анализируйте выходные данные ls .

Вы можете использовать этот один вкладыш:

 for i in *chr*.txt; do ((first  )) amp;amp; echo "$i"; done
  

Альтернативно использование массива:

 # array holding matching files
arr=(*chr*.txt)

# loop through all but first file 
for i in "${arr[@]:1}"; do
    echo "$i"
done