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