
Tenho a infelicidade de lidar com nomes de arquivos que contêm espaços. Quero concatenar arquivos cujos nomes de arquivos contenham espaços. Também quero classificar os nomes dos arquivos numericamente. Obviamente o seguinte falha:
cat $(ls *.sql | sort -n)
desde foo bar.sql
é passado como dois argumentos para cat
. Qual é a abordagem usual aqui?
Responder1
Não há necessidade ls
aqui. É o shell que lista o conteúdo do diretório expandindo o *.sql
glob.
Em um sistema GNU ou FreeBSD:
printf '%s\0' *.sql | sort -nz | xargs -r0 cat --
(usar \0
em vez de \n
junto com -z/-0
garante que também funcione com nomes de arquivos contendo caracteres de nova linha).
Observe que a classificação numérica -n
assume que o número está no início do nome do arquivo.
Ou se você tiver zsh
:
cat ./*.sql(.n)
(O n
qualificador glob serve para habilitar a classificação numérica (também funciona quando o número não está no início, desde que todos os nomes de arquivo tenham o mesmo prefixo (como file12.sql
, file2.sql
). Eu adicionei .
também para incluir apenas arquivos regulares. Adicione D
se você também quiser arquivos ocultos como .foo.sql
).
Responder2
Você pode fazer isso cat $(ls -1)
se substituir o IFS. IFS é a variável shell que informa ao BASH quais caracteres usar como delimitador. O valor padrão para IFS é espaço, tabulação, nova linha. Se você alterar o IFS para apenas nova linha, poderá fazer isso cat $(ls -1)
.
Não há nada de errado com as outras respostas, mas esta pode ser uma resposta mais direta sobre como lidar com espaços em geral e esta resposta apresenta a variável IFS com a qual a maioria não está familiarizada.
#!/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
Saída
[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
Aqui está um link para alguma documentação sobre IFS. http://bash.cyberciti.biz/guide/$IFS. Acho que aprendi sobre isso há muito tempo, lendo o livro BASH de O'Rielly.
Responder3
Use xargs
(assumindo a implementação GNU) com um delimitador personalizado (assumindo que os nomes dos arquivos não contenham novas linhas):
ls -1d -- *.sql | sort -n | xargs -d "\n" cat --