2010-01-28 4 views
9

이 간단한 작업에 find 명령을 사용할 수 있다는 것을 알고 있습니다. 하지만 find 나 ls를 사용하지 말고 일을해야하는 임무가 있습니다. 제발 도와주세요 ....find 또는 ls 명령을 사용하지 않고 bash에서 서브 디렉토리를 재귀 적으로 나열하는 방법은 무엇입니까?

+0

어떻게해야할까요? 자신의 쉘 스크립트, C 프로그램, Java ...? 우리가 사용할 수있는 것을 알려 주면 도움이 더 필요해집니다 :-) – Grundlefleck

+0

'echo *'또는 그 변형을 사용하여'ls '을 에뮬레이트 할 수 있습니다. –

답변

1

du 명령은 하위 디렉토리를 재귀 적으로 나열합니다. 마크 바이어스는 현재의 모든 파일의 목록을 얻을 수 echo *을 사용할 수 있습니다 말했듯이

tree -d 
+0

비어있는 디렉토리가 내 Mac에서 bash를 사용하여 표시됩니다. –

10

하지만 내가 디렉토리 언급을 얻을 수 있는지 확실하지 않습니다

, 예배 규칙서.

test 또는 [] 명령/builtin에는 파일이 디렉토리인지 테스트 할 수있는 옵션이 있습니다.

재귀 적용하고 완료되었습니다.

+1

왜 -1을 얻었습니까? 제발 코멘트. –

+0

나는 당신에게 -1을주지 않았지만, 왜 당신이 그것을 얻었는지는 분명합니다. 왜 대답을 '별칭 bla ls; bla'? 물어 본 질문은 알고리즘을 작성하고'ls'와 같은 일을하지만'ls'라고하지 않는 * command *를 찾지 않았습니다. – vladr

+7

@Vlad Romascanu : 오 ... 알았어.하지만 "find 나 ls를 사용하지 않고 과제를 수행하고 있습니다."find와 ls를 제외한 모든 것이 충분하다는 것을 이해했습니다. ^^ –

1

사용해보십시오

+1

'echo'의 대안으로'for'는 glob 따라서 OP는'for file in *;을 사용할 수 있습니다. ...; 다. – outis

25

당신은 단지 쉘

#!/bin/bash 
recurse() { 
for i in "$1"/*;do 
    if [ -d "$i" ];then 
     echo "dir: $i" 
     recurse "$i" 
    elif [ -f "$i" ]; then 
     echo "file: $i" 
    fi 
done 
} 

recurse /path 

함께 할 또는 수 있습니다 당신은 할 경우 bash는 4.0

#!/bin/bash 
shopt -s globstar 
for file in /path/** 
do 
    echo $file 
done 
아래
+1

트리 명령을 사용하여 downvote하지 않는 이유는 무엇입니까? 또는 에코가있는 메시지는 유효 응답이기도합니다. – ghostdog74

+0

디렉토리가 비어 있다면'dir : bla/*'를 출력합니다. 왜냐하면'bla/*'는 자손이 없으므로 리터럴로 보여지기 때문입니다. 'pushd/popd'를 사용하거나'[[ "$ 1/*"= "$ i"]]를 추가 할 수 있습니다; 다음 계속; fi'를 'do'다음의 첫 번째 줄로 사용한다. – Bogdan

0
$ function f { for i in $1/*; do if [ -d $i ]; then echo $i; f $i; fi; done } 
$ mkdir -p 1/2/3 2/3 3 
$ f . 
./1 
./1/2 
./1/2/3 
./2 
./2/3 
./3 
+1

-1 숙제 질문에 대한 완전한 대답을 제공하려는 경우 숙제 질문에 정확하게 답하십시오. 디렉토리 항목 이름의 공백은 어떨까요? –

+0

이고 디렉토리에 들어 가지 않으며 텍스트 파일을 나열하지 않습니다. – 18446744073709551615

+0

디렉토리를 입력하면 OP가 텍스트 파일 (또는 디렉토리와 다른 파일)에 대해 아무 말도하지 않습니다. 나는 '공간이있는 디렉토리'문제를 해결하지 않을 것이다. –

4

이 하나의 가능한 구현 : AS를

# my_ls -- recursively list given directory's contents and subdirectories 
# $1=directory whose contents to list 
# $2=indentation when listing 
my_ls() { 
    # save current directory then cd to "$1" 
    pushd "$1" >/dev/null 
    # for each non-hidden (i.e. not starting with .) file/directory... 
    for file in * ; do 
    # print file/direcotry name if it really exists... 
    test -e "$file" && echo "$2$file" 
    # if directory, go down and list directory contents too 
    test -d "$file" && my_ls "$file" "$2 " 
    done 
    # restore directory 
    popd >/dev/null 
} 

# recursively list files in current 
# directory and subdirectories 
my_ls . 

운동을하면 abov를 수정하는 방법을 생각할 수 있습니다. e 스크립트에서 파일들에 대한 전체 경로를 인쇄합니다 (단지 들여 쓰기 된 파일/dirnames 대신). pushd/popd (그리고 두 번째 매개 변수 $2)의 필요성을 제거 할 수 있습니다. 또한

if test XYZ ; then command ; fi 완전히 동등 test XYZ && command 사용 (test XYZ이 성공한 경우, 즉 command 실행)을 참고. test XYZ[ XYZ ]과 동일하며 위의 내용은 if [ XYZ ] ; then command ; fi과 동일합니다. 또한 세미콜론 ;은 개행 문자로 바꿀 수 있으며, 이는 동일한 의미입니다.

test -e "$file" && 조건을 제거하고 (echo 만 남음) 어떻게되는지 확인하십시오.

"$file" 주위에 큰 따옴표를 제거하고 목록에있는 내용의 디렉토리에 공백이있는 파일 이름이 있으면 어떻게되는지 확인하십시오. 스크립트 상단에 set -x을 추가하거나 (디버그 출력을 켜고 디버그 출력을 파일로 리디렉션하기 위해 sh -x scriptname.sh 2>debugoutput.txt 실행) 디버그 출력을 켜고 세부적인 내용을 확인하려면 sh -x scriptname.sh으로 호출하십시오.

... 
for file in * .?* ; do 
    if [ "$file" != ".." ] ; then 
    test -e ... 
    test -d ... 
    fi 
done 
... 

!= (문자열 비교)를 사용하는 대신 -ne (숫자 비교 :

또한 숨겨진 파일 (예를 들어, .bashrc)를 나열합니다.일부 쉘 구현에 전달 될 수있는 문자의 수에 엄격한 제한 (~ 4K)가 있다는 것을

my_ls() { 
    # everything in between roundbrackets runs in a separatly spawned sub-shell 
    (
    # change directory in sub-shell; does not affect parent shell's cwd 
    cd "$1" 
    for file in ... 
     ... 
    done 
) 
} 

주 :)

또 다른 기술은 pushd/popd 사용하는 대신 서브 쉘을 산란하는 것 for (또는 모든 내장 명령이나 외부 명령에 대한 인수). 실제로 for을 수행하기 전에 쉘 expands, inline, * to a list of all matching filenames 이후로 많은 파일이있는 디렉토리에서 *이 확장되면 문제가 발생할 수 있습니다 (동일한 문제 실행 중일 때 같은 디렉토리에 ls *라고 말하면 e를 실행할 수 있습니다. e .지. Command too long과 같은 오류가 발생합니다.

+0

'shopt -s dotglob'를 사용하여 숨겨진 파일을 나열 할 수 있습니다. – ghostdog74

+0

@ghostdog - 휴대용이 아닙니다. '. *'(또는'.?'는 배트에서'.'를 건너 뛰기 위해) 트릭을 잘하고 휴대용입니다. – vladr

0

기술적으로 find도 아니고 lsfind2perl | perl 또는 File::Find. 전부
이 (bash가 globstar 유효한 4.0 이상)

shopt -s globstar nullglob dotglob 
echo **/*/ 

: 그것은 떠들썩한 파티를 위해이기 때문에

 
$ find2perl -type d | perl 
$ perl -MFile::Find -e'find(sub{-d&&print"$File::Find::name\n"},".")' 
+0

하지만 그렇다면 파이썬/루비/PHP 등을 사용하여 파일을 나열 할 수있는 언어는 기술적으로'ls' 나'find'를 사용하지 않을 것입니다 – ghostdog74

+0

@ ghostdog74 분명히. 그러나 모든 진지한 답변이 놀라운 피드백보다 적게 들었으므로, 이것은 덜 심각한 것입니다. (실제로 나는 C에서'find '의 클론을 작성하려고했고 컴파일 + 쉘 스크립트는 그것을 실행하지만, 농담을하기에는 너무 많은 노력이라고 결정했다.) – ephemient

3

는,이 이미되어 말했다되지 않았 음을 놀라운이다.
후행 슬래시 /은 디렉토리 만 선택하는 데 사용됩니다.

옵션 globstar** (search recursivelly)을 활성화합니다. 옵션 nullglob은 파일/디렉토리와 일치하지 않으면 *을 제거합니다. 옵션 dotglob에는 점으로 시작하는 파일 (숨김 파일)이 포함되어 있습니다.

관련 문제