Как отсортировать имена файлов, содержащие пробелы, и объединить файлы?

Как отсортировать имена файлов, содержащие пробелы, и объединить файлы?

Мне не повезло иметь дело с именами файлов, содержащими пробелы. Я хочу объединить файлы, имена которых содержат пробелы. Я также хочу отсортировать имена файлов по номерам. Очевидно, что следующее не сработает:

cat $(ls *.sql | sort -n)

поскольку foo bar.sqlпередается в виде двух аргументов в cat. Какой здесь обычный подход?

решение1

Здесь это не нужно ls. Это оболочка, которая выводит список содержимого каталога, расширяя *.sqlглоб.

В системе GNU или FreeBSD:

printf '%s\0' *.sql | sort -nz | xargs -r0 cat --

(использование \0вместо \nвместе с -z/-0гарантирует, что он также будет работать с именами файлов, содержащими символы новой строки).

Обратите внимание, что числовая сортировка -nпредполагает, что число находится в начале имени файла.

Или если у вас есть zsh:

cat ./*.sql(.n)

( nКвалификатор glob позволяет включить числовую сортировку (также работает, когда число не находится в начале, при условии, что все имена файлов имеют одинаковый префикс (например file12.sql, , file2.sql). Я .также добавил, чтобы включить только обычные файлы. Добавьте, Dесли вам также нужны скрытые файлы, например .foo.sql).

решение2

Вы можете сделать это cat $(ls -1), если переопределите IFS. IFS — это переменная оболочки, которая сообщает BASH, какие символы использовать в качестве разделителя. Значение по умолчанию для IFS — пробел, табуляция, новая строка. Если вы измените IFS только на новую строку, то вы можете сделать cat $(ls -1).

В других ответах нет ничего неправильного, но этот ответ может быть более прямым ответом на вопрос, как работать с пробелами в целом, и в этом ответе вводится переменная IFS, с которой большинство не знакомо.

#!/bin/bash
dir=$(mktemp -d)
for x in $(seq 10); do
    echo $x > "$dir/$(date) $x.txt"
done

pushd $dir
ls -1 $dir

# Set IFS to newline only inorder to deal with the spaces in the file names
#
oldIFS=$IFS
IFS=$'\n'


cat $(ls -1 $dir)


IFS=$oldIFS

Выход

[sri@localhost test]$ ./test
/tmp/tmp.IuXCBzbTLj ~/test
Mon Nov 17 06:38:52 EST 2014 10.txt
Mon Nov 17 06:38:52 EST 2014 1.txt
Mon Nov 17 06:38:52 EST 2014 2.txt
Mon Nov 17 06:38:52 EST 2014 3.txt
Mon Nov 17 06:38:52 EST 2014 4.txt
Mon Nov 17 06:38:52 EST 2014 5.txt
Mon Nov 17 06:38:52 EST 2014 6.txt
Mon Nov 17 06:38:52 EST 2014 7.txt
Mon Nov 17 06:38:52 EST 2014 8.txt
Mon Nov 17 06:38:52 EST 2014 9.txt
10
1
2
3
4
5
6
7
8
9

Вот ссылка на документацию по IFS. http://bash.cyberciti.biz/guide/$IFS. Я думаю, что узнал об этом давным-давно, прочитав книгу О'Райли BASH.

решение3

Используйте xargs(предполагая реализацию GNU) с пользовательским разделителем (предполагая, что имена файлов не содержат символов новой строки):

ls -1d -- *.sql | sort -n | xargs -d "\n" cat --

Связанный контент