ファイル名の複数行をカスタム区切り文字で1つに結合する方法は?


441

の結果ls -1を1行に結合して、好きなように区切りたいと思います。

これを達成するために使用できる標準のLinuxコマンドはありますか?

回答:


689

最初のオプションと同様ですが、末尾の区切り文字を省略します

ls -1 | paste -sd "," -

29
ちょうどメモとして、私が試みたpasteのバージョンは、STDINから読み取るように指示するために最後に "-"引数が必要です。たとえば、ls -1 | paste -s -d ":" - それがすべてのバージョンの貼り付けで共通であるかどうか不明
アンディホワイト

4
空の区切り文字を許可するため、これはより良いです:)
Yura Purbeev

2
Note paste-、少なくともmyではデフォルトで(標準入力)を取得しますpaste (GNU coreutils) 8.22
fedorqui 'SO stop harming' 15/07/29

1
私はそれを賛成しました、これは今、そして今それは選択された回答と同じ票を持っています。これが答えです。末尾
デリミタ

1
空の区切り文字はを使用して指定できる"\0"ためpaste -sd "\0" -、私にとってはうまくいきました。
Brad Parks

378

編集:区切り文字をカンマにしたい場合は、単に「ls -m

ああ、パワーとシンプルさ!

ls -1 | tr '\n' ','

カンマ「」を好きなように変更します。これには「末尾のコンマ」が含まれることに注意してください


46
+1、ただしより複雑なバージョンは最後の\ nを別の方法で処理する必要があります
mouviciel

5
ファイル名にが含まれている場合は\n、これも置き換えられます。
codaddict

3
@ShreevatsaR:彼は末尾に ""を付けないことを意味します、と私は信じています。そうですls -1 | tr "\\n" "," | sed 's/\(.*\),/\1/'
Chris

7
@クリス:あなたのsedエンドマーカー文字で、もう少し効率的かもしれない:ls -1 | tr "\\n" "," | sed 's/,$//'; echo ''
pieman72

2
最後のシンボルを削除するためだけにsedafter を使用trするのは無理があるようです。私は行くls -1 | tr '\n' ',' | head -c -1
reddot

29

これは最後のコンマを改行に置き換えます:

ls -1 | tr '\n' ',' | sed 's/,$/\n/'

ls -m 画面幅文字(たとえば80番目)に改行を含めます。

主にBash(ls外部のみ):

saveIFS=$IFS; IFS=$'\n'
files=($(ls -1))
IFS=,
list=${files[*]}
IFS=$saveIFS

Bash 4でreadarray(別名mapfile)を使用する:

readarray -t files < <(ls -1)
saveIFS=$IFS
IFS=,
list=${files[*]}
IFS=$saveIFS

提案してくれたgniourf_gniourfに感謝します。


これは、名前に空白が含まれるファイルを処理しません。これを試してください:dir = / tmp / testdir; rm -rf $ dir && mkdir $ dir && cd / $ dir && touch "this is a file" this_is_another_file && ls -1 && files =($(ls -1))&& list = $ {files [@] /%/ 、} && list = $ {list%*、} && echo $ list
dimir

1
@dimir:この質問に対する答えの多くは、この問題に悩まされています。タブまたはスペースを含むファイル名を許可するように回答を編集しましたが、改行は許可しません。
追って通知があるまで一時停止。

あなたのbashバージョンもパス名の展開に悩まされています。行から配列を構築するには、次のようにmapfile(Bash≥4)を使用することを検討してくださいmapfile -t files < <(ls -1)。をいじる必要はありませんIFS。そして、それも短いです。
gniourf_gniourf 2014年

また、配列がある場合は、を使用IFSしてフィールドを結合できますsaveIFS=$IFS; IFS=,; list=${files[*]}; IFS=$saveIFS。または、1文字以上のセパレータが必要な場合は、別の方法を使用します。
gniourf_gniourf 2014年

1
@gniourf_gniourf:私はあなたの提案を私の回答に含めました。ありがとう。
追って通知があるまで一時停止。

24

これは素晴らしいと思います

ls -1 | awk 'ORS=","'

ORSは「出力レコード区切り文字」であるため、行はコンマで結合されます。


6
これは、末尾の区切り文字を除外しません。
Derek Mahar、2014年

6
これは、複数文字のレコードセパレータ(例えば、取り扱いによるものは特に素晴らしいです" OR "
マットシェーファー

15

の設定IFSと使用の組み合わせ"$*"は、あなたが望むことをすることができます。私はサブシェルを使用しているので、このシェルの$ IFSに干渉しません

(set -- *; IFS=,; echo "$*")

出力をキャプチャするには、

output=$(set -- *; IFS=,; echo "$*")

2
どのようにset機能するかについて、もう少し情報がありますか?私にはブードゥーのように見えます。浅い見通しでman setも多くの情報を得ることができませんでした。
Ehtesh Choudhury 2013

3
あなたが与える場合はset、引数の束が、オプションなしに、それは位置パラメータ($ 1、$ 2、...)を設定します。最初の引数(この場合はファイル名)がダッシュで始まる場合に備え--て保護setする必要があります。の--オプションの説明を参照してくださいhelp set。位置パラメータは、物事のリストを処理する便利な方法だと思います。私はまた、配列でこれを実現している可能性:output=$( files=(*); IFS=,; echo "${files[*]}" )
グレンはジャックマン

追加のプログラムを実行する必要がなく、スペースや改行を含むファイル名でも機能するので、これは素晴らしいことです。
Eric

1
@EhteshChoudhury type setあなたが言うように、set is a shell builtin。だから、man set助けにはならないが、役立つhelp setでしょう。回答:「残りの引数を定位置パラメーターに割り当てます。」
ステフェイン・グーリッホン

の後set -- **1つのレベルの展開を遅らせると、サブシェルがなくても正しい出力が得られる場合がありますIFS=',' eval echo '"$*"'。もちろん、これは位置パラメータを変更します。
Isaac

13

ls一般的な解析はお勧めできません。そのためfind、たとえば、次のように使用することをお勧めします。

find . -type f -print0 | tr '\0' ','

またはfindおよびを使用してpaste

find . -type f | paste -d, -s

複数の行を結合する一般的な方法(ファイルシステムとは関係ありません)については、Unixコマンドラインで簡潔かつ移植可能な「結合」を確認してください。


9

車輪を再発明しないでください。

ls -m

それはまさにそれを行います。


OPは区切り文字を必要としていたので、コンマを変換するにはまだtrが必要です。また、カンマの後にスペースを追加します。つまり、file1、file2、file3
rob

そう使用ls -mしてtr、あなたはどうしたらコンマの後にスペースを削除するls -m | tr -d ' '
アンディ・

2
trを使用すると、ファイル名内のスペースが削除されます。使用することをおsed 's/, /,/g
勧め

7

ただバッシュ

mystring=$(printf "%s|" *)
echo ${mystring%|}

5
"printf -v mystring"%s | "*"を使用すると、$()のフォークを回避できます
camh

しかし、特に、末尾の@camhを混乱させることはありません|
クリストファー

1
まあ、ちょうどbashそしてgnu coreutilsprintf
ThorSummoner

@camhただしprintf -v、bashでのみ機能しますが、提示された回答は多くのシェルタイプで機能します。
アイザック

@Christopherはい、|両方の行が使用されている場合は、末尾のが削除されますprintf -v mystring "%s|" * ; echo ${mystring%|}
アイザック

7

このコマンドは、PERLファン用です。

ls -1 | perl -l40pe0

ここで、40はスペースの8進ASCIIコードです。

-pは行ごとに処理して出力します

-lは、末尾の\ nを、指定したASCII文字で置き換えます。

-eは、コマンドラインの実行を実行していることをPERLに通知します。

0は、実際に実行するコマンドがないことを意味します。

perl -e0はperl -e ''と同じです


6

trの潜在的な改行の混乱を避けるために、-bフラグをlsに追加できます。

ls -1b | tr '\n' ';'

5

答えはすでに存在しているようです。

a, b, cフォーマットが必要な場合は、ls -mTulainsCórdovaの答え)を使用してください

あなたがしたい場合やa b cフォーマット、使用するls | xargs(バージョンsimpified クリス・Jの答えを

それとも、のような他の区切りたい場合に|使用し、ls | paste -sd'|'(のアプリケーションアルテムの答え


5

majkinetorの答えに加えて、これは末尾の区切り文字を削除する方法です(私はまだ彼の答えの下でコメントすることはできないので):

ls -1 | awk 'ORS=","' | head -c -1

デリミタが数えるだけの数の後続バイトを削除します。

複数の文字の区切り文字を使用できるため、このアプローチが好きですawk

ls -1 | awk 'ORS=", "' | head -c -2

編集

Peterが気づいたように、負のバイト数はネイティブMacOSバージョンのヘッドではサポートされていません。ただし、これは簡単に修正できます。

まず、をインストールしcoreutilsます。「GNUコアユーティリティは、GNUオペレーティングシステムの基本的なファイル、シェル、およびテキスト操作ユーティリティです。」

brew install coreutils

MacOSでも提供されるコマンドは、プレフィックス「g」でインストールされます。例えばgls

これを実行したらghead、負のバイト数を持つエイリアスを使用するか、エイリアスを作成します。

alias head="ghead"

注:負のバイト数は特定のバージョンのヘッドでのみサポートされているため、macosなどでは機能しません。
ピーター

それを指摘してくれてありがとう。MacOSの回避策を追加しました。
Aleksander Stelmaczonek

4

sedの方法、

sed -e ':a; N; $!ba; s/\n/,/g'
  # :a         # label called 'a'
  # N          # append next line into Pattern Space (see info sed)
  # $!ba       # if it's the last line ($) do not (!) jump to (b) label :a (a) - break loop
  # s/\n/,/g   # any substitution you want

これは複雑さが線形で、すべての行がsedのパターンスペースに追加された後に一度だけ置換されます。

@AnandRajasekaの回答、およびhereなどの他のいくつかの同様の回答はO(n²)です。これは、sedがパターンスペースに新しい行が追加されるたびに置換する必要があるためです。

比べる、

seq 1 100000 | sed ':a; N; $!ba; s/\n/,/g' | head -c 80
  # linear, in less than 0.1s
seq 1 100000 | sed ':a; /$/N; s/\n/,/; ta' | head -c 80
  # quadratic, hung

3

xargsのバージョンが-dフラグをサポートしている場合、これは機能するはずです。

ls  | xargs -d, -L 1 echo

-dはデリミタフラグです

-dがない場合は、以下を試すことができます

ls | xargs -I {} echo {}, | xargs echo

最初のxargsでは、この例ではコンマである区切り文字を指定できます。


3
-dGNU xargsで入力区切り文字を指定するため、機能しません。2番目の例は、最後の浮遊区切り文字に関する他のソリューションと同じ問題を示しています。
トール

3
sed -e :a -e '/$/N; s/\n/\\n/; ta' [filename]

説明:

-e-実行するコマンドを示します
:a-ラベルです
/$/N-現在と(N)の行の一致の範囲を定義します
s/\n/\\n/;-すべてのEOLを次と置き換えます\n
ta;-一致が成功した場合はラベルaに移動します

私のブログから取られた。



2

lsパイプに接続すると1つの列の出力が生成されるため、-1は冗長です。

以下joinは、末尾の区切り文字を残さない組み込み関数を使用した別のperlの回答です。

ls | perl -F'\n' -0777 -anE 'say join ",", @F'

-0777プログラムが実行される前に、あいまいなものはperlにすべての入力を読み取らせます。

末尾の区切り文字を残さないsed代替

ls | sed '$!s/$/,/' | tr -d '\n'

0

ls-m出力を", "コンマとスペースで区切るオプションがあります。

ls -m | tr -d ' ' | tr ',' ';'

この結果をパイプしtrてスペースまたはコンマを削除すると、結果を再度パイプしtrて区切り文字を置き換えることができます。

私の例,では、区切り文字を区切り文字に置き換えます;

trは引数として渡す文字列の最初の文字しか考慮しないため;、任意の1文字の区切り文字に置き換えます。


0

chompを使用して、複数の行を1行にマージできます。

perl -e 'while(<>){if(/ \ $ /){chomp; }印刷;} 'bad0> test

ifステートメントに改行条件を入れます。特殊文字または任意の区切り文字を使用できます。


0

末尾のスラッシュ処理を備えたクイックPerlバージョン:

ls -1 | perl -E 'say join ", ", map {chomp; $_} <>'

説明する:

  • perl -E:サポート機能を備えたPerlを実行(たとえば...)
  • 言う:キャリア返品で印刷
  • 結合 "、"、ARRAY_HERE:配列を "、"で結合
  • マップ{chomp; $ _}行:各行からキャリアが戻り、結果を返します
  • <>:stdin、各行は行であり、マップと結合して各行の配列を作成します
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.