사용자 정의 구분 기호를 사용하여 여러 줄의 파일 이름을 하나로 묶는 방법은 무엇입니까?


441

ls -1한 줄로 결과를 결합하고 원하는대로 구분하고 싶습니다.

이것을 달성하기 위해 사용할 수있는 표준 Linux 명령이 있습니까?

답변:


689

첫 번째 옵션과 비슷하지만 후행 구분 기호를 생략합니다.

ls -1 | paste -sd "," -

29
참고로, 내가 시도한 페이스트 버전에는 STDIN에서 읽도록 지시하기 위해 끝에 "-"인수가 필요합니다. 예를 들면 ls -1 | paste -s -d ":" - 확실하지 그 페이스트의 모든 버전과 보편적 인 경우
앤디 화이트

4
이 : 빈 구분을 할 수 있기 때문에이 하나 더
유라 Purbeev

2
참고 paste-적어도 my에서 (표준 입력)을 기본값으로 가져옵니다 paste (GNU coreutils) 8.22.
fedorqui 'SO 중지 피해'

1
방금 그것을 찬성했습니다. 이제 지금은 선택한 답변과 동일한 투표를했습니다. 이것은 대답입니다. 후행 delimeter 없음
버그 탐지기

1
빈 구분자를 사용하여 지정할 수 있습니다 "\0", 그래서 paste -sd "\0" -나를 위해 일한!
Brad Parks

379

편집 : 단순히 " 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 번째 문자).

대부분 배쉬 ( ls외부 만 ) :

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

Bash 4에서 readarray(aka 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_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

배열이 있으면 IFS필드를 결합하는 데 사용할 수 있습니다 saveIFS=$IFS; IFS=,; list=${files[*]}; IFS=$saveIFS.. 또는 하나 이상의 문자가있는 구분 기호를 원하는 경우 다른 방법을 사용하십시오.
gniourf_gniourf

1
@gniourf_gniourf : 나는 당신의 제안을 내 대답에 포함시켰다. 감사.
추후 공지가있을 때까지 일시 중지되었습니다.

24

이건 대단해

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

ORS는 "출력 레코드 구분 기호"이므로 이제 행이 쉼표로 결합됩니다.


6
후행 구분 기호는 제외되지 않습니다.
Derek Mahar

6
이는 처리 멀티 문자 기록을 구분 (예, 특히 굉장 " OR ")
매트 샤퍼

15

설정 IFS과 사용의 조합은 "$*"원하는 것을 할 수 있습니다. 서브 쉘을 사용하고 있으므로이 쉘의 $ IFS를 방해하지 않습니다

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

출력을 캡처하려면

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

2
set작동 방식 에 대한 추가 정보 가 있습니까? 저에게 약간 부두처럼 보입니다. 얕게 살펴보면 man set많은 정보 를 얻지 못했습니다.
Ehtesh Choudhury

3
set여러 인수를 제공하지만 옵션은 제공 하지 않으면 위치 매개 변수 ($ 1, $ 2, ...)를 설정합니다. 첫 번째 인수 (또는이 경우 파일 이름)가 대시로 시작되는 경우 --보호해야 set합니다. 의 --옵션 설명을 참조하십시오 help set. 위치 매개 변수가 물건 목록을 처리하는 편리한 방법을 찾습니다. 나는 또한 이것을 배열로 구현할 수 있었다 :output=$( files=(*); IFS=,; echo "${files[*]}" )
glenn jackman

추가 프로그램을 실행할 필요가 없으며 공백이나 줄 바꿈이 포함 된 파일 이름으로 작동하기 때문에 좋습니다.
Eric

1
@EhteshChoudhury type set당신에게 말할 것이다 set is a shell builtin. 따라서 man set도움이되지는 않지만 그렇게 help set할 것입니다. 답 : "-나머지 인수를 위치 매개 변수에 지정하십시오."
Stéphane Gourichon

set -- *. *한 레벨의 확장을 지연 시키면 서브 쉘 없이도 올바른 출력을 얻을 수 있습니다 IFS=',' eval echo '"$*"'. 물론 위치 매개 변수가 변경됩니다.
Isaac


9

바퀴를 재발 명하지 마십시오.

ls -m

정확히 그렇습니다.


OP는 구분자를 원했기 때문에 여전히 쉼표를 변환하려면 tr이 필요합니다. 또한 쉼표 뒤에 공백을 추가합니다. file1, file2, file3
rob

쉼표 뒤에 공백을 사용 ls -m하고 tr제거하기ls -m | tr -d ' '
Andy

2
tr을 사용하면 파일 이름 안의 공백이 삭제됩니다. 더 나은 사용sed 's/, /,/g
glenn jackman

7

그냥 강타

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

5
"printf -v mystring"% s | "*"를 사용하는 것이 약간 더 효율적입니다. $ ()에 대한 포크를 피합니다.
camh

그러나 특히 |@camh 는 후미하지 않습니다 .
Christopher

1
글쎄, 그냥 bash그리고 gnu coreutilsprintf
ThorSummoner

@camh 그러나 printf -vbash에서만 작동 하지만 제시된 답변은 많은 쉘 유형에서 작동합니다.
Isaac

@Christopher 네, |두 줄을 모두 사용 한다면 후행을 제거합니다 printf -v mystring "%s|" * ; echo ${mystring%|}.
Isaac

7

이 명령은 PERL 팬을위한 것입니다.

ls -1 | perl -l40pe0

여기 40은 공간에 대한 8 진 ASCII 코드입니다.

-p는 한 줄씩 처리하고 인쇄합니다.

-l은 후행 \ n을 우리가 제공하는 ASCII 문자로 대체합니다.

-e는 명령 행 실행을 PERL에 알리는 것입니다.

0은 실제로 실행할 명령이 없음을 의미합니다.

perl -e0은 perl -e ''와 동일합니다


6

tr에 대한 줄 바꿈 혼동을 피하기 위해 ls에 -b 플래그를 추가 할 수 있습니다.

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

5

답변이 이미 존재하는 것 같습니다.

네가 원한다면 a, b, c형식ls -m ( Tulains Córdova 's answer )을 사용하십시오.

또는 원하는 경우 a b c 형식ls | xargs ( Chris J의 대답의 단순화 된 버전 )을 사용하십시오.

아니면 같은 다른 구분하려면 |사용을, ls | paste -sd'|'(의 응용 프로그램 아르 템의 대답 )


5

majkinetor의 답변 위에 덧붙여서, 여기에 후행 구분 기호를 제거하는 방법이 있습니다 (아직 그의 대답으로 주석을 달 수 없기 때문에).

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

구분 기호로 계산되는 후행 바이트 수를 제거하십시오.

다중 문자 구분 기호 + 다른 장점을 사용할 수 있기 때문에이 방법이 마음에 듭니다 awk.

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

편집하다

Peter가 알 수 있듯이 기본 MacOS 버전의 head에서는 음의 바이트 수가 지원되지 않습니다. 그러나 이것은 쉽게 고칠 수 있습니다.

먼저을 설치하십시오 coreutils. "GNU 핵심 유틸리티는 GNU 운영 체제의 기본 파일, 셸 및 텍스트 조작 유틸리티입니다."

brew install coreutils

MacOS에서 제공하는 명령은 접두사 "g"와 함께 설치됩니다. 예를 들어gls .

이 작업을 수행하면 ghead음수 바이트 수를 사용하거나 더 나은 별칭을 사용할 수 있습니다 .

alias head="ghead"

참고 : 음수 바이트 수는 특정 버전의 헤드에서만 지원되므로 macos에서는 작동하지 않습니다.
Peter

지적 해 주셔서 감사합니다. 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로 입력 분리 문자를 지정하므로 작동하지 않습니다. 두 번째 예는 마지막에 스트레이 구분 기호의 다른 솔루션과 동일한 문제를 보여줍니다.
Thor

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

설명:

-e-실행할 명령을 나타냅니다
:a.-레이블
/$/N입니다. 현재 및 (N) ext 라인에 대한 일치 범위를 정의합니다
s/\n/\\n/;.-모든 EOL을\n
ta; 하는 경우 -goto 레이블 a로

내 블로그 에서 가져 왔습니다 .



2

ls파이프에 연결할 때 하나의 열 출력을 생성하므로 -1중복됩니다.

다음 join은 후행 구분 기호를 남기지 않는 내장 함수를 사용하는 또 다른 펄 답변입니다 .

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

애매 모호한 -0777프로그램을 실행하기 전에 펄이 모든 입력을 읽게한다.

후행 구분 기호를 남기지 않는 sed 대안

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

0

ls쉼표와 공백으로 -m출력을 구분 하는 옵션 이 ", "있습니다.

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

tr공백을 제거 하기 위해이 결과를 파이핑 하거나 쉼표를 사용하면 tr분리 문자를 대체 하기 위해 결과를 다시 파이핑 할 수 있습니다 .

내 예제에서 구분 기호 ,를 구분 기호 로 바꿉니다.;

대체 ;무엇으로 구분 기호 하나 개의 문자 그럴 필요는 당신이 인수로 전달 문자열의 첫 번째 문자를 차지하고 있기 때문에 당신이 선호합니다.


0

chomp를 사용하여 여러 줄을 한 줄로 병합 할 수 있습니다.

perl -e 'while (<>) {if (/ \ $ /) {chomp; } print;} 'bad0> 테스트

if 문에 줄 바꿈 조건을 넣으십시오. 특수 문자 또는 구분 기호가 될 수 있습니다.


0

후행 슬래시 처리 기능이있는 Quick Perl 버전 :

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

설명하기:

  • perl -E : 기능을 지원하는 Perl을 실행합니다 (예 : ...)
  • 예 : 운송 업체 반송으로 인쇄
  • join ",", ARRAY_HERE : ","로 배열을 조인
  • 지도 {chomp; $ _} ROWS : 각 라인에서 운송 업체가 반환 한 결과를 제거하고 결과를 반환합니다
  • <> : stdin, 각 줄은 ROW, 맵과 연결하여 각 ROW의 배열을 만듭니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.