왜 'ls'를 파싱하지 않는가 (그리고 대신 무엇을해야 하는가)?


204

나는 이 링크 를 인용하여 "파싱하지 마라 ls!" 이것은 몇 가지 이유로 나를 귀찮게합니다.

  1. 그 링크의 정보는 약간의 질문으로 도매로 받아 들여졌지만 캐주얼 독서에서 최소한 몇 가지 오류를 선택할 수는 있습니다.

  2. 또한 그 링크에 명시된 문제가 해결책을 찾고자하는 욕구를 불러 일으키지 않은 것처럼 보입니다.

첫 번째 단락에서 :

... [ls]파일 목록 을 요청할 때 큰 문제가 있습니다. 유닉스는 공백 문자, 줄 바꿈, 쉼표, 파이프 기호 및 거의 모든 다른 문자를 포함하여 파일 이름에 거의 모든 문자를 허용합니다. NUL을 제외한 분리 문자. ... ls파일 이름을 줄 바꿈으로 구분합니다. 이름에 줄 바꿈이있는 파일이 생길 때까지 괜찮습니다. 그리고 줄 ls바꿈 대신 NUL 문자로 파일 이름을 종료 할 수 있는 구현 방법을 모르므로으로 파일 이름 목록을 안전하게 가져올 수 없습니다 ls.

버머 맞지? 어떻게 지금까지 우리는 개행 문자가 개행 문자를 포함 할 수있는 데이터에 대한 상장 데이터 집합을 종결 처리 할 수 있습니까? 글쎄,이 웹 사이트에서 질문에 대답하는 사람들이 매일 이런 종류의 일을하지 않았다면, 우리가 어려움을 겪고 있다고 생각할 수 있습니다.

사실 대부분의 ls구현은 실제로 출력을 구문 분석하기 위해 매우 간단한 API를 제공하며 우리는 그것을 실현하지 않고도 모든 작업을 수행했습니다. 파일 이름을 null로 끝낼 수있을뿐만 아니라 null을 사용하거나 원하는 다른 임의의 문자열로 파일 이름을 시작할 수 있습니다. 또한 파일 유형별로 이러한 임의의 문자열을 할당 할 수 있습니다 . 고려하십시오 :

LS_COLORS='lc=\0:rc=:ec=\0\0\0:fi=:di=:' ls -l --color=always | cat -A
total 4$
drwxr-xr-x 1 mikeserv mikeserv 0 Jul 10 01:05 ^@^@^@^@dir^@^@^@/$
-rw-r--r-- 1 mikeserv mikeserv 4 Jul 10 02:18 ^@file1^@^@^@$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 01:08 ^@file2^@^@^@$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 02:27 ^@new$
line$
file^@^@^@$
^@

자세한 내용은 이것을 참조하십시오 .

이제이 기사의 다음 부분은 실제로 나를 이해시켜줍니다.

$ ls -l
total 8
-rw-r-----  1 lhunath  lhunath  19 Mar 27 10:47 a
-rw-r-----  1 lhunath  lhunath   0 Mar 27 10:47 a?newline
-rw-r-----  1 lhunath  lhunath   0 Mar 27 10:47 a space

문제는의 출력에서 ls사용자 또는 컴퓨터가 파일 이름을 구성하는 부분을 말할 수 없다는 것 입니다. 각 단어입니까? 아니요. 각 줄입니까? 아닙니다.이 질문에 대한 정답은 없습니다 : 당신은 말할 수 없습니다.

또한 ls파일 이름 데이터를 때때로 깨뜨리는 방법에 주목 하십시오 (이 경우 "a""newline"\n 사이의 문자를 ? 물음표 로 바꿨습니다 . ...

...

현재 디렉토리의 모든 파일을 반복하려면 for루프와 glob를 사용하십시오.

for f in *; do
    [[ -e $f ]] || continue
    ...
done

저자는이 호출 파일 이름을 잘못 전달 되면 ls쉘 globs와를 포함하는 파일 이름의 목록을 반환 한 후와 파일 목록을 검색 쉘 글로브를 사용하는 것이 좋습니다!

다음을 고려하세요:

printf 'touch ./"%b"\n' "file\nname" "f i l e n a m e" |
    . /dev/stdin
ls -1q

f i l e n a m e  
file?name

IFS="
" ; printf "'%s'\n" $(ls -1q)

'f i l e n a m e'
'file
name'

POSIX는 피연산자를 다음 -1과 같이 정의 합니다 -q ls.

-q-인쇄 할 수없는 파일 이름 문자 및 <tab>s의 각 인스턴스를 물음표 ( '?') 문자로 작성하십시오. 출력이 터미널 장치에 대한 경우 구현시 기본적으로이 옵션을 제공 할 수 있습니다.

-1- (숫자 1) 출력이 한 줄에 하나씩 입력되도록합니다.

글 로빙에는 고유 한 문제가 없습니다. 어떤 문자 ? 일치 하므로 ?목록에서 여러 개의 일치하는 결과가 동일한 파일과 여러 번 일치합니다. 그것은 쉽게 처리됩니다.

이 작업을 수행하는 방법이 요점은 아니지만 결국에는 많은 시간이 걸리지 않으며 아래에 설명되어 있습니다 . 이유 에 관심이있었습니다 . 내가 생각할 때, 그 질문에 대한 가장 좋은 대답이 받아 들여졌습니다. 사람들이 할 수없는 것보다 할 있는 일을 사람들에게 알리는 데 더 자주 집중하는 것이 좋습니다 . 내가 생각 하듯이 적어도 당신은 틀린 것으로 증명 될 가능성이 훨씬 낮습니다.

그러나 왜 시도조차합니까? 분명히, 나의 주된 동기는 다른 사람들이 나에게 할 수 없다고 계속 말하고 있다는 것이었다. 나는 ls당신이 무엇을 찾아야 하는지를 알기 만하면 출력이 규칙적이고 예측 가능하다는 것을 잘 알고 있습니다. 잘못된 정보는 대부분의 일보다 나를 귀찮게합니다.

그러나 Patrick과 Wumpus Q. Wumbley의 답변 (후자의 멋진 핸들에도 불구하고)을 제외하고는 사실을 제외 하고는 대답 대부분의 정보가 대부분 올바른 것으로 간주합니다. 일반적으로 구문 분석하는 것보다 현재 디렉토리를 검색 할 때 더 효과적 ls입니다. 그들은 내 점에서 적어도 충분한 이유 중 하나는 위의 기사에서 인용 한 잘못된 정보를 전파하거나 그들이 수용 할 명분 있습니다 정당화하기 위해, 그러나 아니다 " 구문 분석되지 않습니다 ls. "

Patrick의 답변의 일관되지 않은 결과는 주로 zshthen을 사용한 결과입니다 bash. zsh-기본적으로- 이식 가능한 방식으로 $(대체 단어를 단어 분리하지 않습니다 ). 그래서 그가 나머지 파일들은 어디로 갔냐 고 물었을 때 ? 그 질문에 대한 대답은 당신의 껍질이 그들을 먹었다는 것입니다. 휴대용 쉘 코드를 SH_WORD_SPLIT사용 zsh하고 처리 할 때 변수 를 설정해야하는 이유가 여기에 있습니다. 나는 그의 답변에서 이것을 지적하지 못한 것이 끔찍한 오도라고 생각합니다.

Wumpus의 대답은 나를 위해 계산되지 않습니다. 목록 컨텍스트에서 ?캐릭터 쉘 글로브입니다. 다른 말을하는 방법을 모르겠습니다.

여러 결과 사례를 처리하려면 글로브의 욕심을 제한해야합니다. 다음은 끔찍한 파일 이름의 테스트 기반을 만들고 표시합니다.

{ printf %b $(printf \\%04o `seq 0 127`) |
sed "/[^[-b]*/s///g
        s/\(.\)\(.\)/touch '?\v\2' '\1\t\2' '\1\n\2'\n/g" |
. /dev/stdin

echo '`ls` ?QUOTED `-m` COMMA,SEP'
ls -qm
echo ; echo 'NOW LITERAL - COMMA,SEP'
ls -m | cat
( set -- * ; printf "\nFILE COUNT: %s\n" $# )
}

산출

`ls` ?QUOTED `-m` COMMA,SEP
??\, ??^, ??`, ??b, [?\, [?\, ]?^, ]?^, _?`, _?`, a?b, a?b

NOW LITERAL - COMMA,SEP
?
 \, ?
     ^, ?
         `, ?
             b, [       \, [
\, ]    ^, ]
^, _    `, _
`, a    b, a
b

FILE COUNT: 12

지금 나는거야 안전한 아닌 모든 문자 /slash, -dash, :colon다음 쉘 글로브에서, 또는 알파 - 숫자 문자 sort -u의 고유 결과에 대한 목록입니다. ls인쇄 할 수없는 문자는 이미 보호 되었으므로 안전합니다. 손목 시계:

for f in $(
        ls -1q |
        sed 's|[^-:/[:alnum:]]|[!-\\:[:alnum:]]|g' |
        sort -u | {
                echo 'PRE-GLOB:' >&2
                tee /dev/fd/2
                printf '\nPOST-GLOB:\n' >&2
        }
) ; do
        printf "FILE #$((i=i+1)): '%s'\n" "$f"
done

산출:

PRE-GLOB:
[!-\:[:alnum:]][!-\:[:alnum:]][!-\:[:alnum:]]
[!-\:[:alnum:]][!-\:[:alnum:]]b
a[!-\:[:alnum:]]b

POST-GLOB:
FILE #1: '?
           \'
FILE #2: '?
           ^'
FILE #3: '?
           `'
FILE #4: '[     \'
FILE #5: '[
\'
FILE #6: ']     ^'
FILE #7: ']
^'
FILE #8: '_     `'
FILE #9: '_
`'
FILE #10: '?
            b'
FILE #11: 'a    b'
FILE #12: 'a
b'

아래에서 문제에 다시 접근하지만 다른 방법론을 사용합니다. \0null 이외 의 /ASCII 문자는 경로명에서 금지 된 유일한 바이트입니다. 여기에 globs를두고 대신 POSIX 지정 -d옵션 ls과 POSIX 지정 -exec $cmd {} +구성을 결합 find합니다. 때문에 find오직 자연스럽게 방출합니다 /순서를은 쉽게 다음은 각 항목에 대한 모든 dentry 정보를 포함 재귀 안정적으로 구분 된 파일 목록을 조달. 다음과 같이 무엇을 할 수 있는지 상상해보십시오.

#v#note: to do this fully portably substitute an actual newline \#v#
#v#for 'n' for the first sed invocation#v#
cd ..
find ././ -exec ls -1ldin {} + |
sed -e '\| *\./\./|{s||\n.///|;i///' -e \} |
sed 'N;s|\(\n\)///|///\1|;$s|$|///|;P;D'

###OUTPUT

152398 drwxr-xr-x 1 1000 1000        72 Jun 24 14:49
.///testls///

152399 -rw-r--r-- 1 1000 1000         0 Jun 24 14:49
.///testls/?
            \///

152402 -rw-r--r-- 1 1000 1000         0 Jun 24 14:49
.///testls/?
            ^///

152405 -rw-r--r-- 1 1000 1000         0 Jun 24 14:49
.///testls/?
        `///
...

ls -i 특히 결과 고유성이 문제가 될 때 매우 유용 할 수 있습니다.

ls -1iq | 
sed '/ .*/s///;s/^/-inum /;$!s/$/ -o /' | 
tr -d '\n' | 
xargs find

이것들은 내가 생각할 수있는 가장 휴대용 수단입니다. GNU ls를 사용하면 다음을 수행 할 수 있습니다.

ls --quoting-style=WORD

마지막으로, inode 번호가 필요할 때 자주 사용 하는 훨씬 간단한 구문 분석ls 방법이 있습니다.

ls -1iq | grep -o '^ *[0-9]*'

그것은 단지 inode 번호를 반환합니다-이것은 또 다른 편리한 POSIX 지정 옵션입니다.


12
@ mikeserv 좋아. 셸 글로브는 2.48 배 빠릅니다. time bash -c 'for i in {1..1000}; do ls -R &>/dev/null; done'= 대 3.18s time bash -c 'for i in {1..1000}; do echo **/* >/dev/null; done'=의 1.28s
패트릭

28
최신 업데이트와 관련하여 코드 작동 여부를 판단 할 때 시각적 출력에 의존하지 마십시오. 출력을 실제 프로그램으로 전달하고 프로그램이 파일에서 조작을 시도하도록하십시오. 이것이 stat실제로 각 파일이 존재하는지 확인하기 때문에 대답 에 사용하고 있는 이유 입니다. sed물건 의 맨 아래에있는 비트 가 작동하지 않습니다.
Patrick

57
당신은 진지 할 수 없습니다. ls처음에 파싱하지 않는 것보다 질문이 설명하는 모든 농구 대를 뛰어 넘는 것이 더 쉽고 간단하거나 어떤 식 으로든 더 나은 방법 은 무엇입니까? 당신이 묘사하는 것은 매우 어렵습니다. 나는 그것을 이해하기 위해 그것을 분해해야하며 상대적으로 유능한 사용자입니다. 평범한 Joe가 이와 같은 것을 처리 할 수있을 것으로 기대할 수 없습니다.
terdon

46
인수를 선택하기 위해 질문을 사용하는 경우 -1입니다. ls출력 구문 분석 이 잘못된 모든 이유 는 원래 링크 (및 기타 여러 위치)에서 잘 설명되었습니다. OP가이를 이해하는 데 도움을 요청했다면이 질문은 합리적이었을 것입니다. 그러나 OP는 단순히 자신의 잘못된 사용법이 괜찮다는 것을 증명하려고합니다.
R ..

14
@mikeserv 그것만이 아닙니다 parsing ls is bad. for something in $(command)정확한 결과를 얻기 위해 단어 분리에 의존하고 의존하는 것은 대부분 command's간단한 결과를 얻지 못하는 사람들에게는 좋지 않습니다.
BroSlow

답변:


184

나는 이것에 대해 전혀 확신하지는 못하지만 , 충분한 노력을 기울일 준비가되어 있다면 , "적대적"의 얼굴 앞에서조차도 믿을만한 결과를 파싱 할 있다는 주장을 가정 해 보자. ls작성한 코드를 알고 있으며 의도적으로 파일 이름을 변경하도록 설계된 파일 이름을 선택하고 있습니다.

그렇게 할 수 있더라도 여전히 나쁜 생각 입니다.

Bourne 쉘은 좋은 언어가 아닙니다. 다른 요소 (예 :)보다 극단적 인 이식성이 더 중요하지 않으면 복잡한 것에 사용하면 안됩니다 autoconf.

나는 당신이 출력을 파싱하는 ls것이 쉘 스크립트에 대한 최소한의 저항 경로처럼 보이는 문제에 직면한다면 , 그것은 당신이하는 일이 쉘에 대해 너무 복잡 하고 전체를 다시 작성해야한다는 강력한 표시라고 주장 한다 펄 또는 파이썬. 다음은 Python의 마지막 프로그램입니다.

import os, sys
for subdir, dirs, files in os.walk("."):
    for f in dirs + files:
      ino = os.lstat(os.path.join(subdir, f)).st_ino
      sys.stdout.write("%d %s %s\n" % (ino, subdir, f))

파일 이름에 특이한 문자가 있으면 문제가 없습니다. 출력 이 모호한 것과 같은 방식으로 출력 ls이 모호하지만 "실제"프로그램에서는 중요하지 않습니다 (이와 같은 데모와는 달리). os.path.join(subdir, f)직접 결과를 사용하십시오 .

똑같이 중요하고, 작성한 내용과 완전히 대조적으로, 6 개월 후에도 여전히 의미가 있으며 약간 다른 것을 수행해야 할 때 쉽게 수정할 수 있습니다. 예를 들어, 도트 파일 및 편집기 백업을 제외하고 기본 이름별로 알파벳 순서로 모든 것을 처리해야한다고 가정하십시오.

import os, sys
filelist = []
for subdir, dirs, files in os.walk("."):
    for f in dirs + files:
        if f[0] == '.' or f[-1] == '~': continue
        lstat = os.lstat(os.path.join(subdir, f))
        filelist.append((f, subdir, lstat.st_ino))

filelist.sort(key = lambda x: x[0])
for f, subdir, ino in filelist: 
   sys.stdout.write("%d %s %s\n" % (ino, subdir, f))

5
이거 좋다 그것은 for in | for in재귀에 대해 말 합니까 ? 잘 모르겠습니다. 그것이 하나라도 될 수는 없습니까? 이것은 지금까지 나에게 맞는 유일한 대답입니다.
mikeserv

10
재귀 없음, 중첩 for루프. os.walk장면 뒤에서 진지하게 무거운 작업을 수행하고 있지만 내부 작업 방식 ls이나 find작업 에 대해 걱정할 필요 이상으로 걱정할 필요가 없습니다 .
zwol

6
기술적 os.walk으로 생성기 객체를 반환 합니다 . 제너레이터는 Python의 게으른 목록 버전입니다. 외부 for-loop가 반복 될 때마다 생성기가 호출되고 다른 서브 디렉토리의 내용을 "수율"합니다. File::Find도움이된다면 Perl의 동등한 기능 은입니다.
zwol

6
당신은 내가 비판하는 문서와 Patrick and Terdon의 답변에 100 % 동의한다는 것을 알고 있어야합니다. 내 대답은 출력 파싱을 피하기 위해 독립적이고 추가적인 이유를 제공하기위한 것 ls입니다.
zwol

19
이것은 매우 잘못된 것입니다. 쉘은 좋은 프로그래밍 언어는 아니지만 프로그래밍 언어가 아니기 때문에 가능합니다. 스크립팅 언어입니다. 그리고 좋은 스크립팅 언어입니다.
Miles Rout

178

정보가 완전히 정확하기 때문에 그 링크는 많은 참조를했으며 매우 오랫동안 사용되었습니다.


ls인쇄 할 수없는 문자를 glob 문자 yes로 대체하지만 해당 문자는 실제 파일 이름에 없습니다. 이것이 왜 중요한가? 두 가지 이유 :

  1. 해당 파일 이름을 프로그램에 전달하면 해당 파일 이름이 실제로 존재하지 않습니다. 실제 파일 이름을 얻으려면 glob를 확장해야합니다.
  2. 파일 glob이 둘 이상의 파일과 일치 할 수 있습니다.

예를 들면 다음과 같습니다.

$ touch a$'\t'b
$ touch a$'\n'b
$ ls -1
a?b
a?b

정확히 같은 두 개의 파일이 어떻게 있는지 주목하십시오. 둘 다 다음과 같이 표현되면 어떻게 구별 a?b합니까?


ls가 쉘 글로브가 포함 된 파일 이름 목록을 반환 한 다음 쉘 글로브를 사용하여 파일 목록을 검색하는 것이 좋습니다.

여기에 차이점이 있습니다. 표시된대로 글로브를 다시 받으면 해당 글로브가 둘 이상의 파일과 일치 할 수 있습니다. 그러나 glob와 일치하는 결과를 반복하면 glob가 아닌 정확한 파일이 다시 나타납니다.

예를 들면 다음과 같습니다.

$ for file in *; do printf '%s' "$file" | xxd; done
0000000: 6109 62                                  a.b
0000000: 610a 62                                  a.b

어떻게 주목 xxd출력을 보여줍니다 $file원시 문자를 포함 \t하고 \n있지를 ?.

를 사용 ls하면 대신이를 얻습니다.

for file in $(ls -1q); do printf '%s' "$file" | xxd; done
0000000: 613f 62                                  a?b
0000000: 613f 62                                  a?b

"나는 사용하지 왜, 어쨌든 반복하는거야 ls?"

당신의 예는 실제로 효과가 없습니다. 작동하는 것처럼 보이지만 작동하지 않습니다.

나는 이것을 언급하고있다 :

 for f in $(ls -1q | tr " " "?") ; do [ -f "$f" ] && echo "./$f" ; done

파일 이름이 많은 디렉토리를 만들었습니다.

$ for file in *; do printf '%s' "$file" | xxd; done
0000000: 6120 62                                  a b
0000000: 6120 2062                                a  b
0000000: 61e2 8082 62                             a...b
0000000: 61e2 8083 62                             a...b
0000000: 6109 62                                  a.b
0000000: 610a 62                                  a.b

코드를 실행하면 다음과 같은 결과가 나타납니다.

$ for f in $(ls -1q | tr " " "?") ; do [ -f "$f" ] && echo "./$f" ; done
./ab
./ab

나머지 파일은 어디로 갔습니까?

대신 시도해 보자.

$ for f in $(ls -1q | tr " " "?") ; do stat --format='%n' "./$f"; done
stat: cannot stat ‘./a?b’: No such file or directory
stat: cannot stat ‘./a??b’: No such file or directory
./ab
./ab
stat: cannot stat ‘./a?b’: No such file or directory
stat: cannot stat ‘./a?b’: No such file or directory

이제 실제 glob을 사용하십시오 :

$ for f in *; do stat --format='%n' "./$f"; done
./a b
./a  b
./ab
./ab
./a b
./a
b

bash로

위 예제는 일반적인 쉘 zsh와 함께 사용되었습니다. bash로 절차를 반복하면 예제와 완전히 다른 결과 집합이 나타납니다.

동일한 파일 세트 :

$ for file in *; do printf '%s' "$file" | xxd; done
0000000: 6120 62                                  a b
0000000: 6120 2062                                a  b
0000000: 61e2 8082 62                             a...b
0000000: 61e2 8083 62                             a...b
0000000: 6109 62                                  a.b
0000000: 610a 62                                  a.b

코드와 근본적으로 다른 결과 :

for f in $(ls -1q | tr " " "?") ; do stat --format='%n' "./$f"; done
./a b
./ab
./ab
./a b
./a
b
./a  b
./ab
./ab
./a b
./ab
./ab
./a b
./a
b
./a b
./ab
./ab
./a b
./a
b

쉘 글로브를 사용하면 완벽하게 작동합니다.

$ for f in *; do stat --format='%n' "./$f"; done
./a b
./a  b
./ab
./ab
./a b
./a
b

bash가 이런 식으로 동작하는 이유는 대답의 시작 부분에서 "파일 글로브가 둘 이상의 파일과 일치 할 수 있습니다"라는 점으로 되돌아갑니다.

lsa?b여러 파일에 대해 동일한 glob ( )을 반환하므로이 glob 를 확장 할 때마다 일치하는 모든 단일 파일을 얻습니다.


내가 사용하고있는 파일 목록을 다시 만드는 방법 :

touch 'a b' 'a  b' a$'\xe2\x80\x82'b a$'\xe2\x80\x83'b a$'\t'b a$'\n'b

16 진 코드는 UTF-8 NBSP 문자입니다.


5
@ mikeserv 실제로 그의 솔루션은 글로브를 반환하지 않습니다. 그 요점을 명확히하기 위해 답변을 업데이트했습니다.
Patrick

18
"나머지 아니에요"? 일관성이없는 동작이며 예기치 않은 결과입니다. 그 이유는 무엇입니까?
Patrick

11
@mikeserv 질문에 대한 내 의견이 보이지 않습니까? 포탄 장갑은보다 2.5 배 빠릅니다 ls. 또한 작동하지 않으므로 코드를 테스트하도록 요청했습니다. zsh는이 중 어떤 것과 관련이 있습니까?
Patrick

27
@ mikeserv 아니요, 여전히 bash에도 적용됩니다. 내가 말하는 것을 듣지 않기 때문에이 질문으로 끝났지 만.
Patrick

7
내가 무슨 생각을 알고 난 것 이 대답을 upvote에 나는 그것이 말하는 모든 것을 동의 내에서 명확하게. ;-)
zwol

54

조금 시도해 보자.

$ touch a$'\n'b a$'\t'b 'a b'
$ ls
a b  a?b  a?b
$ IFS="
"
$ set -- $(ls -1q | uniq)
$ echo "Total files in shell array: $#"
Total files in shell array: 4

보다? 그것은 이미 잘못되었습니다. 3 개의 파일이 있지만 bash는 4를보고합니다. 이는에 의해 전달되기 전에 쉘에 의해 set생성 된 glob이 제공 되기 때문 입니다. 당신이 얻는 이유입니다 :lsset

$ for x ; do
>     printf 'File #%d: %s\n' $((i=$i+1)) "$x"
> done
File #1: a b
File #2: a b
File #3: a    b
File #4: a
b

또는 원하는 경우 :

$ printf ./%s\\0 "$@" |
> od -A n -c -w1 |
> sed -n '/ \{1,3\}/s///;H
> /\\0/{g;s///;s/\n//gp;s/.*//;h}'
./a b
./a b
./a\tb
./a\nb

위의에 실행되었습니다 bash 4.2.45.


2
나는 이것을 찬성했다. 자신의 코드가 당신을 물리 치는 것이 좋습니다. 그러나 내가 잘못했다고해서 그것이 올바르게 이루어질 수 없다는 것을 의미하지는 않습니다. 오늘 아침에 그것을 할 수있는 매우 간단한 방법을 보여주었습니다. 출력을 ls -1qRi | grep -o '^ *[0-9]*'분석 ls하고, inode 번호 목록을 얻는 가장 빠르고 가장 좋은 방법입니다.
mikeserv

38
@ mikeserv : 시간과 인내심이 있다면 올바르게 할 수 있습니다 . 그러나 실제로는 본질적으로 오류가 발생하기 쉽습니다. 당신은 자신이 잘못했습니다. 그 장점에 대해 논쟁하면서! 그것을 위해 싸우는 사람조차도 제대로하지 않으면 그것은 그것에 대한 파업입니다. 그리고 아마, 당신은 아마 그것이 틀리기 전에 더 많은 시간을 틀리게 할 것입니다. 나는 당신에 대해 몰랐지만, 대부분의 사람들은 같은 코드 줄을 가진 연령대를 피하는 것보다 그들의 시간과 더 잘 관계합니다.
cHao

@ cHao-나는 그 장점을 주장하지 않았다-나는 그 선전에 항의했다.
mikeserv

16
@ mikeserv : 그것에 대한 논쟁은 잘 세워지고 가치가 있습니다. 당신도 그것들이 사실임을 보여주었습니다.
cHao

1
@cHao-동의하지 않습니다. 만트라와 지혜 사이에는 그리 나쁘지 않은 선이 있습니다.
mikeserv

50

출력 ls -q은 전혀 문제가되지 않습니다. ?"직접 표시 할 수없는 문자가 있습니다"라는 의미로 사용 됩니다. 글롭 ?은 "모든 문자가 허용됩니다"라는 의미로 사용 됩니다.

globs와는 다른 특수 문자가 ( *[]이상을, 그리고 내부 []쌍 더있다). 그들 중 누구도에 의해 탈출하지 않습니다 ls -q.

$ touch x '[x]'
$ ls -1q
[x]
x

ls -1q출력 을 처리하면 glob 세트가 있고 확장되어 x두 번 얻을뿐만 아니라 [x]완전히 놓칠 수 있습니다. 글로브로서, 문자열 자체와 일치하지 않습니다.

ls -q 셸에 피드백을 줄 수있는 물건을 만들지 말고 미친 캐릭터로부터 눈이나 터미널을 보호하기위한 것입니다.


42

대답은 간단합니다. 특별한 경우는 ls처리 할 수있는 이점보다 중요합니다. ls출력을 구문 분석하지 않으면 이러한 특별한 경우를 피할 수 있습니다 .

여기서 만트라 는 사용자 파일 시스템절대 신뢰하지 않습니다 (사용자 입력절대 신뢰하지 않음 ). 100 % 확실하게 항상 작동하는 방법이 있다면 ls, 동일하지만 덜 확실 하더라도 선호하는 방법이어야합니다 . terdonPatrick이 광범위하게 다루었 으므로 기술적 세부 사항에 대해서는 다루지 않겠습니다 . 나는 ls직업 / 명예가있는 중요한 (그리고 아마도 비싼) 거래에서 사용하는 위험 때문에 피할 수 있다면 불확실성이없는 솔루션을 선호 할 것임을 알고 있습니다.

어떤 사람들은 확실성보다 위험을 선호 하지만 , 버그 보고서를 제출했습니다 .


33

사람들이 절대로 무언가를하지 않는다고 말하는 이유 는 반드시 긍정적으로 올바르게 할 수 없기 때문에 반드시 그런 것은 아닙니다. 우리는 그렇게 할 수는 있지만, 공간적으로나 시간적으로 더 복잡하고 덜 효율적일 수 있습니다. 예를 들어 "x86 어셈블리에 큰 전자 상거래 백엔드를 구축하지 마십시오"라고 말하는 것이 좋습니다.

이제 당면한 문제에 대해 설명했습니다. 시연했듯이 ls를 구문 분석하고 올바른 결과를 제공하는 솔루션을 만들 수 있으므로 정확성은 문제가되지 않습니다.

더 복잡합니까? 예, 그러나 도우미 기능 뒤에 숨길 수 있습니다.

이제 효율성으로

공간 효율성 : 솔루션은 uniq중복을 필터링하는 데 의존 하므로 결과를 느리게 생성 할 수 없습니다. 따라서 O(1)vs. O(n)또는 둘 다 O(n).

시간 효율성 : 모범 사례는 uniq그래서 우리는 여전히이 해시 맵 방식을 사용 O(n)요소의 수에 알고리즘 조달을 그건 아마 불구하고 O(n log n).

이제 진짜 문제 : 알고리즘이 여전히 나빠 보이지 않지만 n에 대한 요소가 아닌 조달 된 요소를 사용하는 것이 정말 조심 스럽습니다 . 그것이 큰 차이를 만들어 내기 때문입니다. \n\nglob을 생성 하는 파일이 있다고 가정하면 ??목록의 2 개 문자 파일마다 일치합니다. 재미있게도 다른 파일 \n\r이 있으면 결과적으로 ??2 개의 문자 파일도 모두 반환합니다. 선형 행동 대신 지수는 확실히 "런타임 행동 악화"로 규정됩니다. 이는 실제 알고리즘과 이론적 CS 저널에 논문을 작성하는 것의 차이점입니다.

모두가 모범을 좋아합니까? 여기 있습니다 "test"라는 폴더를 만들고 폴더가있는 동일한 디렉토리에서이 python 스크립트를 사용하십시오.

#!/usr/bin/env python3
import itertools
dir = "test/"
filename_length = 3
options = "\a\b\t\n\v\f\r"

for filename in itertools.product(options, repeat=filename_length):
        open(dir + ''.join(filename), "a").close()

이 작업 만하는 것은 길이가 7자인 모든 제품을 생성하는 것입니다. 고등학교 수학은 343 개의 파일이어야한다고 말합니다. 인쇄가 정말 빨라야합니다.

time for f in *; do stat --format='%n' "./$f" >/dev/null; done
real    0m0.508s
user    0m0.051s
sys 0m0.480s

이제는 이것을 얻을 수 없기 때문에 첫 번째 해결책을 시도해 봅시다.

eval set -- $(ls -1qrR ././ | tr ' ' '?' |
sed -e '\|^\(\.\{,1\}\)/\.\(/.*\):|{' -e \
        's//\1\2/;\|/$|!s|.*|&/|;h;s/.*//;b}' -e \
        '/..*/!d;G;s/\(.*\)\n\(.*\)/\2\1/' -e \
        "s/'/'\\\''/g;s/.*/'&'/;s/?/'[\"?\$IFS\"]'/g" |
uniq)

리눅스 민트 16에서 작동하는 것 (이 방법의 유용성에 대해 볼륨을 말한다고 생각합니다).

어쨌든 위의 결과는 결과를 얻은 후에 만 ​​결과를 필터링하기 때문에 이전 솔루션은 적어도 후자만큼 빠르지 않아야합니다 (그중 inode 트릭은 없지만 신뢰할 수 없으므로 정확성을 포기합니다).

그래서 지금 얼마나 오래

time for f in $(ls -1q | tr " " "?") ; do stat --format='%n' "./$f" >/dev/null; done

갖다? 글쎄, 나는 정말로 모른다, 343 ^ 343 파일 이름을 확인하는 데 시간이 걸린다-나는 우주의 열사병 후에 당신에게 말할 것이다.


6
물론 다른 답변 아래의 의견에서 언급했듯이 "... 당신은 ls를 구문 분석하고 올바른 결과를 제공하는 솔루션을 만들 수 있음을 시연했습니다 ..."는 실제로 사실이 아닙니다.
와일드 카드

26

OP의 진술 의도

서문 및 원본 답변의 근거 2015 년 5 월 18 일에 업데이트 됨

: mikeserv (영업 이익)는 자신의 질문에 대한 최신 업데이트에 명시된 내가 않는다 " 수치를 고려 그게 내가 처음 불구하고 잘못된 정보의 소스를 지적이 질문을, 불행하게도, 여기에 가장 upvoted 대답은 상당 부분 오해의 소지가합니다. "

글쎄요. 나는 내가 찾을 단지 내 의미를 설명하는 방법을 알아 내려고 너무 많은 시간을 소비하는 것이 아니라 수치이었다 느끼는 것을 내가 같은 질문을 다시 읽어보십시오. 이 질문은 "오히려 답변보다는 [생성] 토론을"결국 과에 무게 결국 텍스트의 ~ 18K 심지어 블로그 게시물에 대한 긴 될 것이다 (단지 명확하게하기 위해, 혼자 질문에 대한).

그러나 StackExchange는 비누 상자가 아니며 블로그가 아닙니다. 그러나 실제로는 적어도 둘 다로 사용했습니다. 사람들은 사람들의 실제 질문에 대답하는 대신 "To-Point-Out"에 많은 시간을 소비했습니다. 이 시점에서 OP는 질문이 전혀 의도 된 것이 아니라고 명시 적으로 언급 했으므로 질문을 우리 형식에 적합하지 않은 것으로 플래그 지정합니다.

이 시점에서 나는 나의 대답이 요점인지 아닌지 확신하지 못한다. 아마 그렇지는 않지만 귀하의 질문 중 일부에 관한 것일 수도 있으며 다른 사람에게 유용한 답변 일 수도 있습니다. 초보자는 마음을 사로 잡습니다. 그 중 일부는 "경험이 없으면" "때때로"로 바뀝니다. :)

일반적으로 ...

남은 거친 가장자리를 용서하십시오. 나는 이미 이것에 너무 많은 시간을 보냈다 ... OP를 직접 인용하지 않고 (원래 의도 한대로) 요약하고 말을 표현하려고합니다.

[원래 답변에서 크게 재 작업]
고려할 때 OP가 내가 대답 한 질문에 대해 강조하고 있다는 강조를 잘못 읽었다 고 생각합니다. 그러나 언급 된 요점 제기되었으며, 나는 그들이 요점이라고 생각하고 초보자에게 조언과 관련하여 다른 맥락에서 제기 된 문제를 해결하기 위해 대답을 크게 그대로 두었습니다.

원래 게시물은 여러 가지 방법으로 여러 기사에서« ls출력을 구문 분석하지 마십시오 »또는« ls출력을 구문 분석해서는 안됩니다» 등과 같은 조언을 제공 한 이유를 물었습니다 .

이 문제에 대한 나의 제안 된 해결책은 이런 종류의 진술의 사례는 단지 약간 다른 방식으로 표현 된 관용구의 예일 뿐이며, 절대 정량자가 명령형 [예 :«하지 말아야 할 X», «[당신은 항상 Y해야한다],«[하나는 절대 Z 야하지 않아야한다»], 특히 절대적인 진실로 의도 된 것이 아니라, 주제에 새로운 사람들에게 주어질 때 일반적인 규칙이나 지침으로 사용되는 진술을 그럼에도 불구하고 그러한 진술의 명백한 형태 .

새로운 주제를 배우기 시작할 때, 왜 다른 방법으로해야하는지에 대해 잘 이해하지 않는 한, 경험이 많은 사람의 지시가없는 한 예외없이 허용 된 일반 규칙을 따르는 것이 좋습니다. 그 자신. 기술과 경험이 높아짐에 따라 특정 상황에서 규칙이 적용되는시기와 여부를 더 결정할 수 있습니다. 일단 당신이 상당한 수준의 경험에 도달하면, 당신은 우선 일반 규칙의 이유를 이해할 것입니다. 그리고 그 시점에서 당신은 규칙의 이유가 어떤 레벨에 적용되는지에 대한 판단을 사용할 수 있습니다. 그 상황, 그리고 우선적으로 우려되는 사항이 있는지에 관한 것입니다.

그리고 아마도 전문가가 아마도 "규칙"을 위반하는 일을 할 수도 있습니다. 그러나 그렇게함으로써 "규칙"이 줄어들지는 않습니다.

그리고, 당면한 주제 : 내 견해로는, 전문가가이 규칙을 완전히 위반하지 않고이 규칙을 위반할 수 있기 때문에 초보자에게 "때때로" 구문 분석 괜찮 ls: 때문에, 출력 이 아니다 . 또는 적어도 초보자가 그렇게하는 것은 옳지 않습니다.

항상 폰을 중앙에 놓으십시오. 개구부에서 한 번의 움직임으로; 가장 빠른 기회의 성; 감독 이전의 기사; 림의 기사는 잔인하다. 항상 계산을 끝까지 볼 수 있는지 확인하십시오! (후회, 미안, 피곤해, 그것은 체스 StackExchange를위한 것입니다.)

규칙, 깨질 것인가?

초보자를 대상으로하거나 초보자가 읽을 수있는 주제에 대한 기사를 읽을 때 종종 다음과 같은 내용이 표시됩니다.

  • " X를 절대로 하지 말아야합니다. "
  • "절대로 Q!"
  • "Z를하지 마십시오."
  • "언제나 Y를해야한다!"
  • "무엇이든 C."

이러한 진술은 확실히 절대적이고 영원한 규칙을 나타내는 것처럼 보이지만, 그렇지 않습니다. 대신에 이것은이 규칙을 읽는 초보자를 위해 적어도 하나의 적절한 방법 인 적어도 하나의 적절한 방법 인 일반적인 규칙 (일명 "지침", "엄지 규칙", "기본 사항"등)을 나타내는 방법입니다. 그러나이 규칙이 절대적인 것으로 명시되어 있기 때문에 규칙은 분명히 반복되는 문제를 다룰 때 얻은 지식을 기록하고 전달하는 방법으로 전문가와 전문가를 우선적으로 구속하지 않습니다. 그들의 특정 기술에 문제.]

이러한 규칙은 전문가가 복잡하거나 미묘한 문제를 어떻게 처리 할 것인지를 밝히지 않을 것입니다. 또는 처음에 규칙으로 이끈 우려는 단순히 적용되지 않습니다. 전문가들은 특정 상황에서 이해가되지 않는 규칙을 어기는 것을 두려워하지 않습니다 (또는 두려워해서는 안됩니다!). 전문가들은 지속적으로 자신의 기술에 대한 다양한 위험과 우려의 균형을 다루고 있으며 이러한 규칙을 어 기고 다양한 요소의 균형을 유지하고 따라야 할 규칙에 의존 할 수없는 판단을 자주 사용해야합니다. 가지고 Goto예를 들어 : 그들이 유해 여부에 긴, 반복, 논쟁이있었습니다. (네,하지 않습니다 gotos를 사용합니다. D)

모달 건의안

적어도 영어로 된 이상한 특징은 다른 많은 언어에서 일반적인 규칙으로 상상할 수 있다는 것입니다. 상황이 적절할 때 규칙을 어길 것이라는 것을 알고 있습니다. 따라서 이러한 진술은 모달 로직의 동일한 진술과 동일하지 않습니다.

이것이 바로 그들이 관용적이어야한다고 말하는 이유입니다. 이러한 규칙은 일반적으로 "never"또는 "always"상황이 아니라 일반적으로 광범위한 상황에 적합한 경향이있는 일반 지침을 체계화하는 데 도움이되며 초보자가 맹목적으로 따라갈 때 훨씬 더 멀어 질 수 있습니다. 정당한 이유없이 그들에 대항하여 선택하는 초보자보다 더 나은 결과. 때로는 규칙을 위반할 때 잘못된 선택을 수반하는 명백한 실패보다는 단순히 표준 이하의 결과로 이어지는 규칙을 체계화합니다.

따라서 일반적인 규칙은 표면에있는 것으로 보이는 절대적인 모달 제안이 아니라 표준 상용구를 사용하여 다음과 같은 규칙을 간단하게 제공합니다.

특정 상황에서이 지침이 잘못되었다고 말할 수있는 능력이없고 자신에게 옳다는 것을 입증 한 경우 $ {RULE}

물론 ls$ {RULE} 대신 "never parse output"을 대체 할 수 있습니다. :)

오 예! 무엇 에 대해 구문 분석 ls출력을?

글쎄, 모든 것을 감안할 때 ... 나는이 규칙이 좋은 규칙이라는 것이 분명하다고 생각합니다. 우선, 실제 규칙은 위에서 설명한 것처럼 관용적 인 것으로 이해되어야합니다 ...

그러나 특정 경우에 쉘 스크립트가 깨질 수 있는지 알기 위해 쉘 스크립팅에 능숙해야하는 것은 아닙니다. 또한 테스트에서 깨뜨 리려고 할 때 잘못되었다고 말하는 데 많은 기술이 필요합니다 ! 그리고 필자는 그러한 기사의 청중 대부분 («의 결과를 파싱하지 마십시오 ls!» 와 같은 조언을 제공 ) 은 그러한 일을 할 수 없으며 그러한 기술을 가진 사람들은 그들은 스스로 알아 내고 어쨌든 규칙을 무시합니다.

그러나 ...이 질문을 보아라. 아마 기술을 가진 사람들조차도 그렇게하는 것이 나쁜 부름이라고 생각했다. 그리고 질문의 저자가 현재의 가장 좋은 예를 찾기 위해 얼마나 많은 노력을 기울였습니까! 나는 거기에있는 사람들의 99 %가 잘못하고 잠재적으로 매우 나쁜 결과를 초래할 것이라는 문제에 대해 당신을 보증합니다 ! 결정된 방법이 좋은 것으로 밝혀 지더라도; lsIT (또는 다른 개발자 )가 파싱 ​​아이디어를 전체적으로 채택하고 많은 테스트 (특히 시간 테스트)를 견딜 수 있고 마지막으로 '공통 기술'상태로 졸업 할 때까지는 많은 사람들이 그것을 시도하고 그것을 잘못 얻을 수 있습니다 ...

그래서 나는 것을 .... 마지막으로 한 번 반복한다 특히이 경우 , 이유를 " 결코 구문 분석하지 ls출력을!" 그것을 표현 하는 올바른 방법입니다.

[업데이트 2014-05-18 : OP의 의견에 대한 답변 (위)에 대한 명확한 추론; 다음은 OP가 어제 질문에 추가 한 것에 대한 답변입니다.]

[업데이트 2014-11-10 : 헤더 추가 및 재구성 / 리팩토링 된 콘텐츠; 그리고 : 재 포맷, 리워드, 명확화 및 음 ... "간결한 구체화"... 나는 이것이 약간의 재 작업으로 바뀌었지만 간단하게 정리되도록 의도했습니다. 나는 그것을 미안한 상태로 남겨 두었으므로 주로 주문을 시도했다. 나는 첫 번째 부분을 그대로 두는 것이 중요하다고 생각했다. 따라서 두 가지 사소한 변경, 중복은 제거되었지만 '그것'이 강조되었습니다.]

† 나는 원래이 내용을 내 원본에 대한 설명으로 만 의도했다. 그러나 반영시 다른 추가 사항을 결정했습니다.

게시물에 대한 지침 은 https://unix.stackexchange.com/tour 를 참조 하십시오.


2
결코 관용적이지 않습니다. 이것은 아무것도 대답하지 않습니다.
mikeserv

1
흠. 글쎄, 나는이 대답이 만족 스러운지 알지 못했지만 논란의 여지 가 없다고 절대 생각하지 않았다 . 그리고 나는 '절대' 그 자체가 관용적 이라고 주장하지 않았다 . 그러나 "X는 절대로하지 마십시오!" 관용적 인 사용 . 'Never / do n't parse ls!'를 보여줄 수있는 두 가지 일반적인 경우가 있습니다 . 올바른 조언은 다음과 같습니다. 1. 출력을 구문 분석 할 수있는 모든 사용 사례가 ls어떤 방식 으로든 사용 가능한 다른 솔루션을 가지고 있음을 입증합니다 (만족스럽게) . 2. 인용 된 경우에 그 진술이 문자적인 것이 아님을 보여주십시오.
shelleybutterfly

귀하의 질문을 다시 살펴보면, 분석에 잘 들어간 "never ..."보다는 "do n't ..."를 먼저 언급 했으므로 그 점에 대해서도 분명히 설명하겠습니다. 이 시점에서 이미 첫 번째 유형의 솔루션이 있습니다.이 솔루션은 만족스럽게 입증 / 설명되어 있으므로 많이 조사하지는 않습니다. 그러나 나는 내 대답을 약간 명확히하려고 노력할 것이다.
shelleybutterfly

1
그 게시물을 정리해야합니다. 그러나 결코 없다 되지 문구 그것은 올바른 방법. 사람들이 다른 사람들에게 절대로 말 하거나 하지 말라고 말할 자격이 있다고 생각하는 것은 조금 우스운 일입니다. 그것이 효과가 있다고 생각하지 않는 이유와 그 이유를 알지만, 무엇이 효과가 있으며 왜 그런지 아는 것은 아닙니다. ls컴퓨터 유틸리티입니다- 컴퓨터 출력을
mikeserv

1
글쎄, 나는 적어도 당신이 신고하는 것에 대해 당신의 권리를 가지고 있기 때문에 나의 하향 투표를 취소했습니다. 오늘 밤이나 내일 청소하려고 노력하겠습니다. 내 생각은 대부분의 코드 예제를 내가 생각하는 답변으로 옮길 것입니다. 그러나 여전히 관심이있는 한 자주 인용되는 블로그 게시물의 부정확성을 변명하지는 않습니다. 나는 사람들이 bash 매뉴얼을 인용하는 것을 그만두기를 바란다. 적어도 POSIX 스펙을 인용 한
후에야

16

ls특정 경우 의 출력을 구문 분석 할 수 있습니까? 확실한. 디렉토리에서 inode 번호 목록을 추출하는 아이디어는 좋은 예입니다. 구현의 ls지원 을 알고 -q있으므로 각 파일이 정확히 한 줄의 출력을 생성하므로 필요한 모든 inode 번호를 파싱합니다. ls -Rai1q출력은 확실히 가능한 솔루션입니다. 물론 저자가 이전에 "ls의 출력을 구문 분석하지 마십시오"와 같은 조언을 보지 못했다면 아마도 줄 바꿈이있는 파일 이름에 대해서는 생각하지 않았을 것이며 결과적으로 'q'를 생략했을 것입니다. 이 경우에는 코드가 미묘하게 손상 될 수 있습니다. 따라서 구문 분석 ls의 출력이 합리적인 경우에도이 조언은 여전히 ​​유용합니다.

넓은 점은 쉘 스크립팅 초보자가 (예를 들어) 어떤 디렉토리에서 가장 큰 파일, 또는 어떤 디렉토리에서 가장 최근에 수정 된 파일입니다, 자신의 첫 번째 본능 구문 분석하는 스크립트 그림을 가지고하려고 할 때,이다 ls's을 (를) 출력- ls초보자가 처음 배우는 명령 중 하나 이기 때문에 이해할 수 있습니다.

불행히도, 그 본능은 잘못되었고, 그 접근법은 깨졌습니다. 더 불행하게도, 그것은 미묘하게 망가졌습니다. 대부분의 시간 동안 작동하지만 코드를 알고있는 누군가가 악용 할 수있는 엣지 케이스에서는 실패합니다.

초보자 ls -s | sort -n | tail -n 1 | awk '{print $2}'는 디렉토리에서 가장 큰 파일을 얻는 방법으로 생각할 수 있습니다 . 이름에 공백이있는 파일이있을 때까지 작동합니다.

그래, ls -s | sort -n | tail -n 1 | sed 's/[^ ]* *[0-9]* *//'어때? 이름에 줄 바꿈이있는 파일이있을 때까지 잘 작동합니다.

파일 이름에 줄 바꿈이있을 때의 인수에 추가 -q하면 ls도움이됩니까? 파일 이름의 같은 지점에 인쇄 할 수없는 문자가 포함 된 2 개의 다른 파일이있을 때까지의 것처럼 보일 수 있습니다. 그런 다음 ls출력은 파일 중 가장 큰 파일 을 구별하지 못하게합니다. 더 나쁜 것은 "?"를 확장하기 위해 아마도 자신의 쉘에 의지 eval할 것입니다. 예를 들어,

foo`/tmp/malicious_script`bar

않습니다 --quoting-style=shell(당신이 경우에 도움이 ls심지어 그것을 지원)? 아니요, 여전히 표시됩니까? 인쇄 할 수없는 문자의 경우 여러 개의 일치 항목 중 가장 큰 것이 여전히 모호합니다. --quoting-style=literal? 아뇨 --quoting-style=locale또는 --quoting-style=c가장 큰 파일의 이름을 모호하지 않게 인쇄해야하지만 나중에 파일로 무언가를 수행 해야하는 경우에는 도움이되지 않을 수 있습니다-인용 부호를 취소하고 실제 파일 이름으로 돌아가는 코드가 많을 수 있습니다. gzip으로 전달할 수 있습니다.

그리고 모든 작업이 끝날 때, 그가 가지고있는 것이 모든 가능한 파일 이름에 대해 안전하고 정확하더라도 읽을 수없고 유지할 수 없으며 파이썬이나 펄 또는 루비에서 훨씬 쉽고 안전하고 읽기 쉽습니다.

또는 다른 쉘 도구를 사용하더라도 머리 꼭대기에서 나는 이것이 트릭을 수행해야한다고 생각합니다.

find . -type f -printf "%s %f\0" | sort -nz | awk 'BEGIN{RS="\0"} END{sub(/[0-9]* /, "", $0); print}'

그리고 최소한 휴대 성이 좋아야합니다 --quoting-style.


오, 크기에 대해 사실-아마도 내가 시도하면 그렇게 할 수 있습니다. 임 좀 피곤하거나이 모든 것은 - 당신이 말하는 그나마 때문에 당신의 대답처럼 수 없습니다 또는 해달라고하지결코 실제로 어쩌면의 예를 제공 하지 왜 와 비교 하는 방법 다른 감사합니다 -.
mikeserv

당신이 시도하면 생각보다 훨씬 어렵다는 것을 알게 될 것입니다. 예, 시도해 보는 것이 좋습니다. 내가 생각할 수있는 한 파일명을 계속 알려 드리겠습니다. :)
godlygeek

의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
terdon

@ mikeserv와 godlygeek, 나는이 주석 스레드 를 채팅으로 옮겼습니다 . 댓글에 이와 같이 긴 토론을하지 마십시오. 이것이 바로 채팅입니다.
terdon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.