'ls -1': 확장명없이 파일 이름을 나열하는 방법


24

ls -1 내 요소를 다음과 같이 나열합니다.

foo.png
bar.png
foobar.png
...

다음 .png과 같이 나열하지 않기를 바랍니다 .

foo
bar
foobar
...

(dir은 .png파일 만 포함 합니다)

grep이 경우 어떻게 사용하는지 말해 줄 수 있습니까 ?

목적 : 확장자없이 모든 이름이 나열되는 텍스트 파일이 있습니다. 텍스트 파일을 폴더와 비교하여 누락 된 파일을 확인하는 스크립트를 만들고 싶습니다.


36
이와 같은 요청에주의를 기울이고 싶습니다. Linux에는 파일 이름 확장자가 없습니다. Linux에는 파일 이름이 포함되거나 포함되지 않을 수 .있습니다. 협약에 파일 이름을 말한다하더라도 .png말에, 나는 PNG 파일이 이름이없는 이유 이유가 없다 foo.zip거나 my.picture.20160518아니면 그냥 mypic.
hymie

2
@hymie 알고 있지만 해당 폴더의 모든 요소 이름은 끝에 .png로 지정됩니다.
Colin

14
"확장"이란 무엇입니까? 이것은 유닉스 파일 이름의 일부가 아닙니다. VMS / NT / Windows에서 이월됩니다. 그리고 당신 젊은이들도 내 잔디밭을 벗어납니다. :)
mpez0

28
이것을 과장하지 말자. OS는 확장자를 단순히 파일 이름의 일부로 취급하지만, 많은 유닉스 프로그램이 컴파일러에서 GUI에 이르기까지주의를 기울입니다. 이 개념은 유닉스와 다른 것이 아닙니다.
알렉시스

1
일반적으로 파일 이름에```탭 문자 가 발생할 가능성이 있기 때문에 및 의 출력을 구문 분석하지 않고 출력ls 을 파이프 하지 않는 것이 좋습니다 . 파일 이름이 제안 된 솔루션 중 많은 경우 문제가 발생합니다. lsfindnewlineThe new art of working on .png\NEWLINE files and other formats
Hastur

답변:


41

이 작업에는 쉘만 필요합니다.

POSIXly :

for f in *.png; do
    printf '%s\n' "${f%.png}"
done

zsh:

print -rl -- *.png(:r)

4
필요가 없습니다 printf; echo ${f%.png}충분할 것입니다.
David Conrad

11
@Conrad : 파일 이름이 대시로 시작하거나 이스케이프 된 시퀀스를 포함하는 경우 일부 경우 에코 사용이 제대로 작동하지 않습니다.
cuonglm


35
ls -1 | sed -e 's/\.png$//'

sed명령 제거합니다 문자열은 (, 그것은 빈 문자열로 대체) .png상기 발견 끝에 파일 이름의.

.로 이스케이프 \.가 해석되도록 sed리터럴로 .문자가 아닌 정규 표현식 .(수단은 어떤 문자와 일치합니다). 이 $줄 끝 앵커이므로 .png파일 이름 중간에 일치하지 않습니다 .


4
나는 영업 이익이 원하는 생각 어떤 아마 제거 확장,하지만 "마지막 하나를". 따라서 다음과 같이 다른 좋은 대답을 수정하십시오.sed 's/\.[^.]*$//'
Otheus

1
그렇습니다. 그 정규 표현식은 그 경우에 효과가있을 것입니다. 그러나 OP가 원한다면 구체적으로 ".png없이 나열하고 싶다"고 말하는 대신 그렇게해야합니다.
cas

4
-1기본값은 필요하지 않습니다.
jlliagre

3
@jlliagre 나는 cas가 동의 -1해야한다고 동의 합니다. 파이프가 켜져있을 때만 기본값이며 일부에게는 숨겨진 놀라움입니다. 따라서 명시 적으로 작성하면 이해하는 데 도움이됩니다. 또한 스크립트 에서이 작업을 수행하므로 어떤 종류의 출력이 기대되는지 알 수 있습니다.
Otheus

1
경고.png 개행 문자 앞에 키 ( ) 가있는 파일 이름의 경우 .png마지막 파일뿐만 아니라 그 이름 도 지워 집니다. ls의 결과를 파이프하고 파싱하는 것을 피하는 것이 좋으며, 종종 숨겨진 놀라운 놀라움을 예약합니다 ...
Hastur

16

bash를 사용하려면 다음을 수행하십시오.

for i in *; do echo "${i%.png}"; done

당신은 도달해야 grep하는가에 대한 대체 /하지 제거, 일치를 발견 할 때 sed더 적합 :

find . -maxdepth 1 -name "*.png"  | sed 's/\.png$//'

PNG 파일에서 순서를 가져 오기 위해 일부 서브 디렉토리를 작성해야한다고 결정하면 다음과 같이 쉽게 변경할 수 있습니다.

find . -name "*.png"  | sed 's/\.png$//'

LS -1 | sed 's / .png //'는 훌륭하게 작동합니다. 고맙습니다!
Colin

find 파이프sed당신이 키 (가진 파일 찾을 경우 솔루션은 몇 가지 문제를 제시 할 수 .png이름의 일부로서 단지 개행 문자 이전을). find또는 의 결과를 파이프하고 파싱하는 것을 피하는 것이 좋습니다. ls종종 숨은 놀라움을 예약합니다.
Hastur

아마도 마지막 예 find와 같은 것으로 대체 될 것 echo입니다. 어떤 용도로 find사용 되는지 명확하지 않으며 결과는 디렉토리 구조에 따라 다릅니다 (예 : 디렉토리가있는 경우 files.png)

@BroSlow보다 합리적인 것으로 업데이트되었습니다.
Anthon

13

내가 가고 싶어 basename합니다 (GNU 구현을 가정)

basename --suffix=.png -- *.png

파이프에서 파이프를 사용하려면 GNU 기본 이름 -z(또는 --zero) 옵션을 사용하여 NUL로 구분 된 (줄 바꿈으로 구분 된) 출력을 생성하는 것이 도움이 될 수 있습니다 .
Toby Speight

11

또 다른 매우 유사한 대답 (이 변형이 아직 나타나지 않은 것에 놀랐습니다)은 다음과 같습니다.

ls | sed -n 's/\.png$//p'
  • 당신은 필요하지 않습니다 -1에 대한 옵션을 ls하기 때문에, ls표준 출력이 터미널이 아닌 경우 (이이 경우에, 파이프의) 것으로 가정합니다.
  • '기본적으로 줄을 인쇄하지 않음' -nsed의미 하는 옵션
  • /p대체의 끝에 있는 옵션은 '... 그리고 대체가 이루어진 경우이 행을 인쇄합니다'를 의미합니다.

그 효과는로 끝나는 줄만 인쇄 .png하고 .png제거하는 것입니다. 즉, 이것은 디렉토리에 .png파일 만 포함되어 있지 않은 OP의 질문에 대한 약간의 일반화를 제공 합니다.

sed -n기술은 grep + sed를 사용하는 경우에 종종 유용합니다.


나는 당신이 돌보는 방법이 당신의 답을 쓰는 것을 좋아합니다. 이 솔루션은 개행을 포함하여 파일 이름에 문제가 있으며 이름 의 첫 부분은 인쇄하지 않습니다. .png개행 문자 앞에 키 ( ) 가있는 초기 단계 인 경우 더 좋습니다.이 경우 마지막 부분 만 지우지 않고 png없이 해당 부분을 인쇄합니다. ls당신이 생각하지 않는 곳에 문제가 숨겨 질 수 있기 때문에 출력을 파싱 (및 파이프)하는 것을 피하기 위해 종종 제안됩니다 .
Hastur

2
@Hastur 원칙적으로 정확하고, 병리 파일 이름을 전달할 때 더 많은 문제 (및 해결책)를 분석하지 않는 유명한 페이지 해석 에 관한 페이지가 있습니다. 그러나 가장 좋은 방법은 병적 인 파일 이름피하는 것입니다 (doh!). 그리고 만약 당신이 할 수없는, 또는 당신이 경우에 있어야합니다 그들에 대한 견고, 다음 중 하나를 사용 find하거나 - 아마도 더 나은 - 더 강력한 언어를 사용하는 것보다 sh(사실을 관리 할 sh 수있는 이 최선의 선택에있어 것을 의미하지 않는다 모든 것을 할을 각각의 경우). 쉘은 먼저 사용성을 위해 설계되었습니다.
노먼 그레이

원칙적으로 사용성에 대해 동의하지만 각 변형이있는 파일 이름 이 있으면이 변형이 실패합니다 . 예를 들어, GUI에서 pdf의 행을 복사하여 붙여 넣을 때 쉽게 눈에 띄지 않을 수 있으므로 병적 인 파일 이름 만 피해야한다고 생각합니다 .
Hastur

더욱이 IMHO 파싱을 시작하기는 쉽지만 ls향후 문제가 발생할 수 있습니다. 종종 우리는 이미 한계를 잊어 버릴 때 나중에 사용할 스크립트를 만듭니다 ... (인간적이며 일반적입니다). 나는 (순수 쉘이기 때문에) cuonglm의 단단하고 posix 호환에 더 나은 것으로 생각하더라도 (파이프가 있거나 없는) 예를 제안 했습니다 . find-exec
Hastur

@Hastur : 미래의 문제는 어쨌든 일어날 것입니다. 시스템의 많은 것들이 줄 바꿈이있는 파일에 대해 강력하지 않습니다. 예를 들어 locate또는 사용하십시오 make.
reinierpost

8

외부 도구없이 BASH 명령 만 사용하면됩니다.

for file in *; do echo "${file%.*}"; done 

이것은 / usr / bin이 없을 때 유용하며 this.is.image.png와 같은 파일 이름 및 모든 확장명에 적합합니다.


6

파싱 ls하거나 파이프 하는 것은 안전하지 않습니다 find[ 1 , 2 ]

구문 분석하는 것이 안전 (및 파이프)의 출력되지 않습니다 ls또는 find이 가능한에서 찾을 주로하기 때문에, 파일 이름 은 AS가 아닌 보통의 문자 줄 바꿈 ... 여기 순수한 쉘주기가 작동합니다 [ cuonglm ] . 옵션과 함께 파이프되지 않은 명령
조차도 작동합니다.find-exec

find ./*.png  -exec  basename {} .png  \;

업데이트 / 메모 : find .숨겨진 파일을 검색하거나 숨겨지지 않은 파일 find ./*.png만 가져 오는 데 사용할 수 있습니다. 으로 find *.png -exec ...당신이 경우에 문제가있을 수 있습니다 그것은라는 이름의 파일이 존재 .png발견이 옵션으로 그것을 얻을 때문입니다. 로 -maxdepth 0명명 된 디렉토리 Dir_01.png에서 또는 find ./*.png -prune -exec ...maxdepth가 허용되지 않는 경우 (Stéphane 덕분에) 내림차순 을 피하기 위해 추가 할 수 있습니다 . 해당 디렉토리를 나열하지 않으려면 옵션을 추가해야합니다 -type f(다른 유형의 비정규 파일도 제외 함). man사용 가능한 모든 옵션에 대한보다 완전한 파노라마를 살펴보고 더 나은 이식성을 위해 POSIX 호환시기를 확인하십시오.

더 많은 단어

예를 들어 문서에서 제목을 복사하고 파일 이름에 붙여 넣으면 하나 이상의 줄 바꿈이 파일 이름 자체에서 끝날 수 있습니다. 제목에 줄 바꿈 직전에 사용해야 할 키조차 포함 할 수 없을 정도로 운이 좋지 않을 수도 있습니다.

The new art of working on .png
files and other formats.

테스트하려면 명령을 사용하여 이와 같은 파일 이름을 만들 수 있습니다

touch "A file with two lines"$'\n'"and This is the second.png"
touch "The new art of working on .png"$'\n'"files and other formats.png"

인쇄 할 수없는 문자 대신 단순 /bin/ls *png출력?

A file with two lines?and This is the second.png
The new art of working on .png?files and other formats.png

당신은 어느 것 모든 경우에 출력 파이프ls또는 find다음 명령을 본 라인은 새로운에서 오는 경우 이해하는 힌트가 없습니다 파일 이름 이나는 다음 경우 개행 선행에 문자 파일 이름을 . 에이불쾌한 참 이름,하지만 여전히 법적 하나.

[ params -Expansion] 쉘이있는 쉘 사이클 은 [ cuonglm ], [ Anthon1 ]${parameter%word} 과 함께 printf또는 echo작동 합니다.

for f in *.png; do printf "%s\n" "${f%.png}" ; done

Shell Parameter Expansion의 매뉴얼 페이지에서 [ 3 ]

$ {parameter % word}
$ {parameter %% word}

... 확장 결과는 일치 패턴이 가장 짧은 ( '%'경우) 또는 일치하는 가장 긴 일치 패턴 ( '%%')이있는 매개 변수의 값입니다.


또한 find명령 결과는 약간 변수입니다 (예 :라는 디렉토리가있는 경우 files.png)

1
친애하는 @BroSlow, 위의 답변을 썼을 때 해당 시점에 존재하는 다른 변형 중 13 개 (모두)를 스크립트에서 명령 호출로 쉘 호출의 인수로 시작했습니다. 동일한 방식으로 행동하고 예상대로 행동하는지 알려주십시오. bash 4.3.11대시 0.5.7-4, zsh (필요한 경우) 5.0.2로 테스트했습니다 . 더 많은 내용을 추가하는 이 게시물 을 자유롭게 읽으십시오 . 나는 이것을 명시 적으로 제안 하기 위해 출력 을 파이핑 하는 것에 대해 동의 하며 제목에 썼습니다. . find-exec:-)
Hastur

위키를 다시 읽으십시오. 나는 여전히 당신이 당신의 예제에서 파이프해야한다고 생각합니다. 그것이 여기서 논의되고 있기 때문입니다. 그리고 최신 버전의 대부분의 ls경우 출력이 파이프되거나 리디렉션 될 때 문제가 없지만 wiki에서 언급했듯이 모든 기능이 작동하지 않을 수 있습니다. ?출력이 터미널로 전송 될 때 대부분 특수 문자 대신에 문자를 삽입합니다 . 즉 Do echo *.png | od -cls *.png | od -c. 개행 문제는의 문제가 아니며 ls파이프의 양쪽에서 null로 끝나지 않는 명령의 문제입니다.

1
printf "${f%.png}\n"잘못되었습니다. 첫 번째 인수는 형식이므로 변수 데이터를 사용해서는 안됩니다. DoS 취약점 ( %1000000000s.png예를 들어 파일로 시도)으로 간주 될 수도 있습니다 .
Stéphane Chazelas

당신 find ./*.png -prune -exec...은 파일 이름으로 시작하는 데 문제 가 있거나 (또는 -디렉토리 타입의 파일, -maxdepth휴대용이 아닌 것에 주의하십시오 )
Stéphane Chazelas

4

충분하지 않습니까?

ls -1 | sed 's/\.png//g'

또는 일반적으로

ls -1 | sed 's/\.[a-z]*//g'

모든 확장을 제거합니다


그러나 다른 솔루션도 작동합니다.
Colin

당신의 질문은 ls -1로 시작했기 때문에 ls -1은 그렇게해야합니다. :)
Rohail Abbas

-1기본값은 필요하지 않습니다.
jlliagre

@Rohail Abbas 그러나 모든 시스템에 sed가 설치되어 있지는 않습니까?
Colin

1
실제로, 그러나 ls출력이 터미널이 아닌 경우 옵션이 없으면 어쨌든 수행됩니다.
jlliagre

3

사용 rev:

ls -1 | rev | cut -f 2- -d "." | rev

rev모든 문자열 (행)을 반대로 바꿉니다. 첫 번째 '.'이후에 모든 것을 자릅니다. rev는 남은 자들을 다시 되 돌린다.

grep'alma' 를 원한다면 :

ls -1 | rev | cut -f 2- -d "." | rev | grep 'alma'

-1기본값은 필요하지 않습니다.
jlliagre

2
이것은라는 이름의 파일에 심하게 실패My.2016.Summer.Vacation.png
데이비드 콘래드

@DavidConrad 나의 나쁜 : / 나는 수정했다cut -f 2-
Tom Solid

이제는 파일과 함께 작동하지만 파일 .png바로 뒤에 개행 문자 가있는 파일은 작동하지 않습니다 ... ls놀람을 잘 숨기고 있기 때문에 구문 분석을 피하는 것이 좋습니다 ... :-)
Hastur

2

디렉토리에 확장자가 .png 인 파일 만 있다는 것을 알고 있다면 방금 실행했을 것입니다. ls | awk -F. '{print $1}'

filename.extension이있는 경우 첫 번째 "필드"를 반환합니다.

예:

[rsingh@rule51 TESTDIR]$ ls
10.png  1.png  2.png  3.png  4.png  5.png  6.png  7.png  8.png  9.png

[rsingh@rule51 TESTDIR]$ ls | awk -F. '{print $1}'
10
1
2
3
4
5
6
7
8
9

불행하게도이 모든에 실패합니다 파일 이름을 두 개 이상으로 ., 같은 Image.1.png심지어와 사람에 없는 좋은 이름 내부에 특수 문자,. 개행 또는 IN (입력) 레코드 세퍼레이터로서 사용하는 것과 awk, RS. ls예상하지 않을 때 발생할 수있는 문제를 숨기는 것을 좋아하므로 출력 을 구문 분석하지 않는 것이 좋습니다 . 해당 참조 1 또는 2 에서 더 많은 내용을 읽을 수 있습니다 . BTW는 awk를 사용하는 것이 좋았습니다 ... 나는 하나의 대답에 몇 가지 예를 넣었습니다.
Hastur

그러나 Colin이 제공 한 샘플을 감안할 때 제대로 작동합니다. 제안한 경우에 적용하려면 다음과 같이 변경하십시오. [rsingh @ rule51 TESTDIR] $ ls | sed -e 's / .png $ //'10 1 2 3 4 5 6 7 8 9 harry.the.bunny whats.a.png.filename 어렵지 않지만 콜린의 필요에 따라 확실하지 않습니다 ls를 파싱하는 문제
rsingh

죄송합니다 ... 방금 'ls'의 출력을 수정하기 전에 파일과 함께 디렉토리를 표시하지 않음을 알았습니다. [rsingh @ rule51 TESTDIR] $ ls 10.png 2.png 4.png 6.png 8.png harry.the.bunny.png 1.png 3.png 5.png 7.png 9.png whats.a.png.filename.png [rsingh @ rule51 TESTDIR] $ ls | sed -e 's / .png $ //'10 1 2 3 4 5 6 7 8 9 harry.the.bunny whats.a.png. 파일 이름
rsingh

note1. 에서 \.내부 를 이스케이프 처리해야 sed -e 's/\.png$//'하지만 방금 작성된 답변이됩니다. :-( note2 당신은 ... awk와 같은 것을 사용하려고 시도 할 수 ls | awk -F. '{if ($NF=="png") {for (i=1;i<NF-1;i++) printf("%s.", $i) ; printf $(NF-1)"\n"}}'있지만 줄이 도착하고 있는지 파일 이름 안에 줄 바꿈이 있는지 여부를 알 수없는 문제가 항상 있습니다. .
Hastur

감사합니다 Hastur, 나는 그것을 놓쳤다 :). 또한이 경우 sed에 찬성하여 awk를 사용하지 않았습니다.
rsingh

2

귀하의 의견에 따르면 "확장자없이 모든 이름이 나열되는 텍스트 파일이 있습니다. 텍스트 파일과 폴더를 비교하여 누락 된 파일을 확인하는 PHP 스크립트를 작성하고 싶습니다":

for file in $(cat yourlist) ; do
  [ -f "${file}.png" ] || {
    echo "$file : listed in yourlist, but missing in the directory"
  }
done
#assumes that filenames have no space...
# otherwise use instead:
#  while IFS= read file ; do ...(same inner loop as above)... ; done < yourlist

반대의 경우 :

for file in *.png ; do
  grep "^${file%.png}$" yourlist >/dev/null || {
    echo "$file: present in the directory but not listed in yourlist"
  }
done
#I assume there are no spaces/tabs/? before/after names in 'yourlist'. Change the script accordingly if there are some (or sanitize the list)

1

ls -l | sed 's/\.png$//'

@roaima가 강조한 가장 정확한 방법입니다. 이스케이프 된 \.png파일이 없으면 이름 a_png.png은 다음과 같습니다 a_.


을 사용 ls -l하면 파일 세부 정보가 제공되므로 OP가 요청한 내용이 아닙니다.
Anthon

1

간단한 쉘 라인 (ksh, bash 또는 zsh; 대시는 아님) :

set -- *.png; printf '%s\n' "${@%.png}"

간단한 기능 (확장자 없음) :

ne(){ set -- *.png; printf '%s\n' "${@%.png}"; }

또는 주어진 확장자를 제거하는 함수 (기본적으로 png) :

ne(){ ext=${1:-png}; set -- *."$ext"; printf '%s\n' "${@%.${ext}}"; }

로 사용:

ne jpg

출력이 별표 *인 경우 해당 확장자를 가진 파일이 없습니다.


1

수퍼 레이터가 ls 인 출력은 다음과 같습니다. 모든 파일에는 name.png가 있으므로 첫 번째 열을 인쇄합니다.
ls | awk -F"." '{print $1}'


-1

sed에 액세스 한 경우 마지막 파일 확장자가 무엇이든간에 (png, jpg, tiff 등) 더 좋습니다.

ls | sed -e 's/\..*$//'

7
같은 파일 이름을 바꿉니다 this.is.a.dotty.txt. s/\.[^.]*$//대신 시도하십시오 .
roaima
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.