
残念ながら、スペースを含むファイル名を扱う必要があります。ファイル名にスペースを含むファイルを連結したいのですが、ファイル名を数値順に並べ替えたいのですが、次の方法は明らかに失敗します。
cat $(ls *.sql | sort -n)
foo bar.sql
は 2 つの引数として に渡されるのでcat
、ここでの通常のアプローチは何でしょうか?
答え1
ここでは必要ありませんls
。glob を展開してディレクトリの内容を一覧表示するのはシェルです*.sql
。
GNU または FreeBSD システムの場合:
printf '%s\0' *.sql | sort -nz | xargs -r0 cat --
(\0
の代わりに を\n
と一緒に使用する-z/-0
と、改行文字を含むファイル名でも機能するようになります)。
数値によるソートでは、-n
数字がファイル名の先頭にあることを前提としていることに注意してください。
または、次の場合zsh
:
cat ./*.sql(.n)
( glob 修飾子は数値ソートを有効にするためのものです (すべてのファイル名に同じプレフィックス ( 、n
など) がある場合、数字が先頭にないときにも機能します) 。通常のファイルのみを含めるためにもを追加しました。のような隠しファイルも必要な場合は を追加します)。file12.sql
file2.sql
.
D
.foo.sql
答え2
IFS をオーバーライドすれば、これを行うことができますcat $(ls -1)
。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/ガイド/$IFS。O'Rielly の BASH の本を読んで、ずっと前にこれを知ったと思います。
答え3
カスタム区切り文字(ファイル名に改行が含まれていないことを前提)とともに使用しますxargs
(GNU 実装を前提としています)。
ls -1d -- *.sql | sort -n | xargs -d "\n" cat --