현재 디렉토리의 모든 파일을 재귀 적으로 확장하는 것은 무엇입니까?
과 **/*.ext
일치하는 모든 하위 디렉토리의 모든 파일로 확장된다는 것을 알고 *.ext
있지만 현재 디렉토리에서도 이러한 모든 파일을 포함하는 유사한 확장은 무엇 입니까?
이것은 Bash 4에서 작동합니다.
ls -l {,**/}*.ext
이중 별표 glob이 작동하려면 globstar
옵션을 설정해야합니다 (기본값 : on).
shopt -s globstar
에서 man bash
:
글롭 스타 설정하면 파일 이름 확장에 사용되는 ** 패턴이 연결됩니다. 텍스트는 파일 및 0 개 이상의 디렉토리와 일치하며 하위 디렉토리. 패턴 뒤에 /가 있으면 디렉터리와 하위 디렉터리가 일치합니다.
이제 globstar 처리에 버그가 있었는지 궁금합니다. 이제 단순히 사용하여 ls **/*.ext
올바른 결과를 얻고 있기 때문 입니다.
그럼에도 불구하고 kenorb가 VLC 저장소를 사용하여 수행 한 분석을 살펴 보았고 해당 분석과 바로 위의 대답에서 몇 가지 문제를 발견했습니다.
find
지정 -type f
에는 다른 파일 유형 (특히 디렉토리)이 포함되지 않고 ls
나열된 명령이 포함 되기 때문에 명령 의 출력에 대한 비교 는 유효 하지 않습니다 . 또한 나열된 명령 중 하나는 ls -1 {,**/}*.*
위의 내 것을 기반으로하는 것처럼 보이지만 하위 디렉터리에있는 파일에 대해 점이 포함 된 이름 만 출력합니다 . OP의 질문과 내 대답에는 특정 확장자를 가진 파일이 있기 때문에 점이 포함됩니다.
그러나 가장 중요한 것은 ls
globstar 패턴과 함께 명령을 사용하는 데 특별한 문제가 있다는 것입니다 **
. 패턴이 Bash에 의해 검사되는 트리의 모든 파일 이름 (및 디렉토리 이름)으로 확장되기 때문에 많은 중복이 발생합니다. 확장 후 ls
명령은 각각 과 디렉토리 인 경우 내용을 나열 합니다 .
예:
현재 디렉토리에는 하위 디렉토리 A
와 그 내용이 있습니다.
A
└── AB
└── ABC
├── ABC1
├── ABC2
└── ABCD
└── ABCD1
해당 트리에서 **
"AA / AB A / AB / ABC A / AB / ABC / ABC1 A / AB / ABC / ABC2 A / AB / ABC / ABCD A / AB / ABC / ABCD / ABCD1"(7 개 항목)으로 확장됩니다. . 그렇게 echo **
하면 정확한 출력을 얻을 수 있으며 각 항목은 한 번 표시됩니다. 그러나 그렇게 ls **
하면 각 항목 의 목록이 출력 됩니다. 그래서 본질적 ls A
으로 ls A/AB
, 등 이 뒤 따르 므로 A/AB
두 번 표시됩니다. 또한 ls
각 하위 디렉토리의 출력을 별도로 설정합니다.
...
<blank line>
directory name:
content-item
content-item
따라서 using wc -l
은 모든 빈 줄과 디렉토리 이름 섹션 제목을 계산하여 훨씬 더 많이 계산합니다.
이것은 당신이 파싱ls
해서는 안되는 또 다른 이유 입니다.
As a result of this further analysis, I recommend not using the globstar pattern in any circumstance other than iterating over a tree of files in this manner:
for entry in **
do
something "$entry"
done
As a final comparison, I used a Bash source repository I had handy and did this:
shopt -s globstar dotglob
diff <(echo ** | tr ' ' '\n') <(find . | sed 's|\./||' | sort)
0a1
> .
I used tr
to change spaces to newlines which is only valid here since no names include spaces. I used sed
to remove the leading ./
from each line of output from find
. I sorted the output of find
since it is normally unsorted and Bash's expansion of globs is already sorted. As you can see, the only output from diff
was the current directory .
output by find
. When I did ls ** | wc -l
the output had almost twice as many lines.
This wil print all files in the current directory and its subdirectories which end in '.ext'.
find . -name '*.ext' -print
You can use: **/*.*
to include all files recursively (enable by: shopt -s globstar
).
Please find below testing of other variations and how they behave.
Testing folder with 3472 files in the sample VLC repository folder:
(Total files of 3472 counted as per: find . -type f | wc -l
)
ls -1 **/*.*
- returns 3338ls -1 {,**/}*.*
- returns 3341 (as proposed by Dennis)ls -1 {,**/}*
- returns 8265ls -1 **/*
- returns 7817, except hidden files (as proposed by Dennis)ls -1 **/{.[^.],}*
- returns 7869 (as proposed by Dennis)ls -1 {,**/}.?*
- returns 15855ls -1 {,**/}.*
- returns 20321
So I think the most closest method to list all files recursively is the first example (**/*.*
) as per gniourf-gniourf comment (assuming the files have the proper extensions, or use the specific one), as the second example gives few more duplicates like below:
$ diff -u <(ls -1 {,**/}*.*) <(ls -1 **/*.*)
--- /dev/fd/63 2015-04-19 15:25:07.000000000 +0100
+++ /dev/fd/62 2015-04-19 15:25:07.000000000 +0100
@@ -1,6 +1,4 @@
COPYING.LIB
-COPYING.LIB
-Makefile.am
Makefile.am
@@ -45,7 +43,6 @@
compat/tdestroy.c
compat/vasprintf.c
configure.ac
-configure.ac
and the other generate even further duplicates.
To include hidden files, use: shopt -s dotglob
(disable by shopt -u dotglob
). It's not recommended, because it can affect commands such as mv
or rm
and you can remove accidentally the wrong files.
$ find . -type f
That will list all of the files in the current directory. You can then do some other command on the output using -exec
$find . -type f -exec grep "foo" {} \;
That will grep each file from the find for the string "foo".
Why not just use brace expansion to include the current directory as well?
./{*,**/*}.ext
Brace expansion happens before glob expansion, so you can effectively do what you want with older versions of bash, and can forego monkeying with globstar in newer versions.
Also, it's considered good practice in bash to include the leading ./
in your glob patterns.
'development' 카테고리의 다른 글
값으로 jQuery 선택 옵션 요소 (0) | 2020.09.15 |
---|---|
adb devices 명령이 작동하지 않음 (0) | 2020.09.14 |
Instruments ObjectAlloc : 라이브 바이트 및 전체 바이트 설명 (0) | 2020.09.14 |
C # 스타일 가이드? (0) | 2020.09.14 |
매니페스트 파일을 생성 / 편집하려면 어떻게합니까? (0) | 2020.09.14 |