쉘 스크립트에서 디렉토리의 파일 목록을 얻는 방법은 무엇입니까?


159

쉘 스크립트를 사용하여 디렉토리의 내용을 가져 오려고합니다.

내 스크립트는 다음과 같습니다

for entry in `ls $search_dir`; do
    echo $entry
done

$search_dir상대 경로는 어디 입니까? 그러나 $search_dir이름에 공백이있는 많은 파일이 있습니다. 이 경우이 스크립트는 예상대로 실행되지 않습니다.

나는 사용할 수 있다는 것을 알고 for entry in *있지만 현재 디렉토리에서만 작동합니다.

나는 그 디렉토리로 바꿀 수 있다는 것을 알고 사용했다가 for entry in *다시 변경하지만 내 특정 상황으로 인해 그렇게 할 수 없습니다.

나는이 개 상대 경로를 $search_dir하고 $work_dir, 나는 그들에게 등을 생성 / 그 안에 파일을 삭제, 읽기, 동시에 모두 일해야

이제 어떻게해야합니까?

추신 : 나는 bash를 사용합니다.

답변:


274
for entry in "$search_dir"/*
do
  echo "$entry"
done

4
for entry in "$search_dir/*"작동하지 않는지 설명 할 수 있습니까 ? 왜 우리 /*는 따옴표 밖에 두어야 합니까?
mrgloom

6
@mrgloom : 쉘에서 와일드 카드를 가져와야하기 때문입니다.
Ignacio Vazquez-Abrams

하지 않을 find빠르다?
Alexej Magura

4
솔루션은 전체 경로를 제공합니다. 현재 디렉토리에있는 내용 만 나열하려면 어떻게해야합니까?
ThatsRightJack

1
@mrgloom 당신이 그렇게하고 싶다면 당신은 그것을 달성 할 수 있습니다for entry in "${search_dir}/*"
funilrys

28

여기에있는 다른 답변은 훌륭하고 귀하의 질문에 대답하지만, 이것은 "bash 디렉토리의 파일 목록 가져 오기"(파일 목록을 저장하려고했습니다)에 대한 최고의 Google 검색 결과이므로 그 문제에 대한 답 :

ls $search_path > filename.txt

특정 유형 (예 : .txt 파일) 만 원하는 경우 :

ls $search_path | grep *.txt > filename.txt

$ search_path는 선택 사항입니다. ls> filename.txt는 현재 디렉토리를 수행합니다.


grep을 사용하여 .txt 파일 만 가져올 필요는 없습니다 :`ls $ search_path / *. txt> filename.txt '. 그러나 더 중요한 것은 파일 이름을 구문 분석하기 위해 ls 명령의 출력을 사용해서는 안됩니다.
Victor Zamanian

1
@VictorZamanian, ls파일 이름을 파싱 하기 위해 출력을 사용해서는 안되는 이유를 자세히 설명해 주 시겠습니까? 전에는 들어 본 적이 없습니다.
samurai_jane

1
@samurai_jane이 주제와 관련하여 제공 할 링크가 많이 있지만 여기에 첫 번째 검색 결과 인 mywiki.wooledge.org/ParsingLs가 있습니다. 나는 ls의 출력을 파싱하지 않는 이유가 BS 였고 그것에 대해 매우 정교하다고 주장하면서 여기에 대한 질문을 보았습니다. 그러나 답변 / 답변은 여전히 ​​나쁜 생각이라고 주장했습니다. 보라 : unix.stackexchange.com/questions/128985/...은
빅터 Zamanian

26

이것은 구문이 이해하기 더 쉬운 곳에서 수행하는 방법입니다.

yourfilenames=`ls ./*.txt`
for eachfile in $yourfilenames
do
   echo $eachfile
done

./는 현재 작업 디렉토리이지만 경로를 바꿀 수 있습니다.
*.txtanything.txt를 반환합니다 . 터미널에 명령을 바로
입력하여 쉽게 나열 할 내용을 확인할 수 있습니다 ls.

기본적으로 yourfilenameslist 명령이 개별 요소로 반환하는 모든 것을 포함 하는 변수 를 만든 다음 반복합니다. 루프는 반복되는 변수 eachfile의 단일 요소 (이 경우 파일 이름)를 포함 하는 임시 변수 를 만듭니다 . 이것은 다른 답변보다 반드시 낫지는 않지만 ls명령과 for 루프 구문에 이미 익숙하기 때문에 직관적 입니다.


이것은 빠르고 비공식적 인 스크립트 또는 한 줄짜리에서는 작동하지만 glob 기반 솔루션과 달리 파일 이름에 줄 바꿈이 포함되어 있으면 중단됩니다.
Soren Bjornstad 님이

@SorenBjornstad 조언 감사합니다! 파일 이름에 줄 바꿈이 허용되는지 몰랐습니다. 어떤 종류의 파일이있을 수 있습니까? 마찬가지로, 이것은 일반적으로 발생하는 것입니까?
rrr

파일 이름의 줄 바꿈은 이러한 이유로 인해 악의적이며 내가 아는 한 합법적 인 이유는 없습니다. 나는 야생에서 한 번도 본 적이 없다. 즉, 이것을 악용하는 방식으로 줄 바꿈으로 파일 이름을 악의적으로 구성하는 것이 가능합니다. (예를 들어, 디렉토리에 파일을 포함하는 상상 A, B그리고 C. 당신은라는 파일을 생성 B\nC하고 D다음 삭제를 선택. 소프트웨어를 당신이하지 않은 경우이 권리가 아니라도 기존 파일 B와 C를 삭제 끝낼 수 처리하지 않는 권한은 해당 작업을 수행합니다).
소렌 Bjornstad에게

19
for entry in "$search_dir"/* "$work_dir"/*
do
  if [ -f "$entry" ];then
    echo "$entry"
  fi
done

11
find "${search_dir}" "${work_dir}" -mindepth 1 -maxdepth 1 -type f -print0 | xargs -0 -I {} echo "{}"

1
나는 이것이 꽤 오래되었다는 것을 알고 있지만 마지막 xargs -0 -i echo "{}"명령 을 얻을 수없는 것 같습니다 . 특히 그 -i echo "{}"역할은 무엇입니까? 또한 더 이상 사용되지 않는 man페이지 에서 읽었으며 insted를 -i사용해야합니다 -I.
drkg4b

1
-i{}arg로 대체 합니다.
Noel Yap

감사! 이것은 나처럼 느린 마음에도 유용합니다 . 명령으로 {}일치하는 문자열로 바뀌는 문자열 이라고 생각합니다 find.
drkg4b

3
왜 사용 xargs합니까? 기본적으로 find찾은 내용을 인쇄합니다 -print0. 에서 모든 것을 삭제할 수 있습니다 .
gniourf_gniourf 오전

1
그렇게하면 공백이있는 파일 항목을 잘 처리하지 못합니다.
Noel Yap

4
$ pwd; ls -l
/home/victoria/test
total 12
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  a
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  b
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  c
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:32 'c d'
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  d
drwxr-xr-x 2 victoria victoria 4096 Apr 23 11:32  dir_a
drwxr-xr-x 2 victoria victoria 4096 Apr 23 11:32  dir_b
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:32 'e; f'

$ find . -type f
./c
./b
./a
./d
./c d
./e; f

$ find . -type f | sed 's/^\.\///g' | sort
a
b
c
c d
d
e; f

$ find . -type f | sed 's/^\.\///g' | sort > tmp

$ cat tmp
a
b
c
c d
d
e; f

변형

$ pwd
/home/victoria

$ find $(pwd) -maxdepth 1 -type f -not -path '*/\.*' | sort
/home/victoria/new
/home/victoria/new1
/home/victoria/new2
/home/victoria/new3
/home/victoria/new3.md
/home/victoria/new.md
/home/victoria/package.json
/home/victoria/Untitled Document 1
/home/victoria/Untitled Document 2

$ find . -maxdepth 1 -type f -not -path '*/\.*' | sed 's/^\.\///g' | sort
new
new1
new2
new3
new3.md
new.md
package.json
Untitled Document 1
Untitled Document 2

노트:

  • . : 현재 폴더
  • -maxdepth 1재귀 적으로 검색하려면 제거
  • -type f: 디렉토리가 아닌 파일 찾기 ( d)
  • -not -path '*/\.*' : 돌아 오지마 .hidden_files
  • sed 's/^\.\///g': ./결과 목록에서 접두사 제거

0

다음은 디렉토리 내에 파일을 나열하는 다른 방법입니다 (다른 답변보다 효율적이지 않은 다른 도구 사용).

cd "search_dir"
for [ z in `echo *` ]; do
    echo "$z"
done

echo *현재 디렉토리의 모든 파일을 출력합니다. for루프는 표준 출력으로 각 파일의 이름과 지문을 반복 처리.

또한 디렉토리 안의 디렉토리를 찾으면 이것을 for루프 안에 넣으십시오.

if [ test -d $z ]; then
    echo "$z is a directory"
fi

test -d 파일이 디렉토리인지 확인합니다.


0

허용 된 답변은 파일 접두어를으로 반환하지 않습니다. 그렇게하려면

for entry in "$search_dir"/* "$search_dir"/.[!.]* "$search_dir"/..?*
do
  echo "$entry"
done

-1

Linux 버전에서 (x86_64 GNU / Linux)로 다음 작업을 수행합니다.

for entry in "$search_dir"/*
do
  echo "$entry"
done

-1 : 변수를 인용하지 않는다는 점을 제외하고 는 허용 된 답변 과 동일 합니다. 인용 부호 $search_dir가 없으면 디렉토리 이름에 공백이 있으면 끊어짐을 의미합니다. (이 경우 인용하지 않고 도망 갈 수 $entry있지만 인용 하는 것이 더 좋습니다.)
Soren

당신은 잘못. 내 대답은 수락 된 답변과 비슷하더라도 동일하지 않습니다. 그리고 그것은 잘못이 아닙니다. 작동합니다. Mac OS를 포함한 다른 유닉스 시스템에서 시도한 것은 다음과 같습니다. 이름에 공백이있는 경우에도 공백이있는 파일이 올바르게 표시됩니다. search_dir =. $ search_dir / *에 입력하십시오. $ entry를 반향하십시오; done ./ aa aaa.txt ./add ./apm_tables.txt 솔루션이 작동하지 않거나 잘못된 결과를 생성 할 수 있음을 증명할 수있을 때 솔루션에 투표 할 수 있습니다.
Andrushenko Alexander 2016 년

내 의견을 조금 더 읽으면 파일 이름이 아닌 디렉토리 이름에 공백이있는 문제가 표시됩니다 . 이는 질문자가 발생한 문제와는 다르지만 여전히 코드가 의도하지 않게 중단 될 수 있음을 의미합니다! 작동하지 않는 예는 다음과 같습니다 .. 루프가 두 번 인쇄 되고 한 번 인쇄 되고 두 번째로 실행 되는데 이는 예상 한 결과가 아닙니다. mkdir "x y"; touch "x y/1.txt"; search_dir="x y"; for entry in $search_dir/*; do echo $entry; donexy/*
Soren Bjornstad 2018 년

그리고 인용되지 않은 부적절한 변수는 위험하다고 잘못 생각합니다. 파일을 남기면서 검색 디렉토리의 서브 디렉토리를 삭제하려면이 코드를 고려하십시오 search_dir="x y"; for entry in $search_dir/*; do if [ -d "$entry" ]; then rm -rf "$entry"; fi; done. 또한이 있다면 x현재 디렉토리에있는 디렉토리, 간략하게 당신이 당신의 변수를 인용하지 않았기 때문에 삭제됩니다!
Soren Bjornstad 2018 년

글쎄, 당신은 항상 하나의 작업을 위해 생성 된 코드를 가져 와서 작업을 약간 변경하면 코드가 잘못됩니다. 질문에 대해 제안 된 솔루션이 작동하도록 요청했습니다. 그러나 ... 개발자 인 나는 당신의 주장에 동의해야합니다 : wenn 우리는 코드를보다 강력하고 일반적으로 만들 수 있습니다. qoutes를 추가하겠습니다. 이것은 내 대답을 위에 주어진 대답과 동일하게 만들지 만, 토론을 위해 (누군가에게 유용 할 수 있음) 대답도 남겨 둡니다.
Andrushenko Alexander 2016

-1

이 간단한 명령을 입력하십시오.

ls -d */

@Michael Sisko
Vipul

ls (목록) -d (디렉토리 만 나열) * / (모든 패턴의 백 슬래시는 목록 만 디렉토리로 제한합니다).
Michael Sisko
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.