파일 이름에 공백, *, ?, $, % 등이 포함된 디렉터리의 파일 목록을 제공해야 하는 스크립트를 작성 중입니다. 어떡하지, 많은 게시물을 봤지만 나에게 맞는 게시물을 찾을 수 없습니다. grep을 사용하여 이것이 가능합니까?
답변1
printf '<%s>\n' *[[:space:]*?$%]*
숨겨진 파일은 보고하지 않습니다. [[:space:]]
멀티바이트 간격 문자( 예 " "
:전자기 4중) UTF-8)은 쉘에 따라 다릅니다(일부는 dash
아직 멀티바이트 문자를 인식하지 못합니다).
예:
$ touch sane 'a%b' $'with\nnewline' $'with space' $'with em-quad'
$ printf '<%s>\n' *[[:space:]*?$%]*
<a%b>
<with em-quad>
<with
newline>
<with space>
답변2
*
안전한 파일 목록을 생성하려면 find를 사용하지 않고 따옴표 없이 사용하세요.
$ echo *
테스트할 몇 가지 파일을 살펴보겠습니다.
$ mkdir test-dir; cd test-dir
$ touch clean normal_file 'a%b' 'has two spaces' '*' 'a*b' '?' 'a?b'
$ touch '$' 'a$b' '%' 'a%b' $'new\nline' $'em\u2001quad' 'normal_file'
이 echo *
명령은 위의 파일을 생성합니다.
? $ * % a?b a$b a*b a%b clean em quad has two spaces new
line normal_file
공백으로 구분된 목록입니다. 예, 줄 바꿈 문자가 포함된 파일 이름이 있기 때문에 두 줄이 있습니다.
파일을 보는 더 쉬운 방법은 파일 이름을 인용 하고 깨끗한 파일 목록을 얻는 printf '%q'
것처럼 새 줄을 추가하는 것입니다 .printf '%q\n'
$ printf '%q\n' *
\?
\$
\*
%
a\?b
a\$b
a\*b
a%b
clean
$'em\342\200\201quad'
has\ two\ spaces
$'new\nline'
normal_file
물론 일반 *와 같이 전체가 아닌 일부 파일을 선택해야 합니다.
따라서 일치하는 모든 문자가 포함된 패턴을 만듭니다 ?$*%
.
그러나 이러한 문자의 대부분은 "특수" 문자이므로 특정 명령에 나타날 때 인용되어야 합니다. 특히, *
또는 ?
뒤에 오는 경우 $
셸에 의해 확장되므로 문제가 발생할 수 있습니다.
must be quoted 그런 다음 다른 모든 문자 를 인용하는 간단한 방법은 다음을 사용하는 것 $
입니다 . 백슬래시가 꼭 필요하지 않은 경우 나쁜 영향은 없으며 이스케이프된 문자는 계속 작동합니다. 이 목록에 공백 문자를 추가해야 합니다. 그러나 새로운 노선의 추가는 심각한 문제가 되었다. 문자 클래스에서 개행 문자를 처리하는 가장 간단한 방법은 를 사용하는 것입니다 . 여기에는 개행 문자, 공백, 탭 및 기타 공백 문자(예: em 대시)가 포함됩니다.printf '%q' ?\$*%
\?\$\*%
[[:space:]]
따라서 명령은 다음과 같습니다.
$ printf '%q\n' *[\?\$\*%[:space:]]*
\?
\$
\*
%
a\?b
a\$b
a\*b
a%b
$'em\342\200\201quad'
has\ two\ spaces
$'new\nline'
clean
및 파일 이름은 필수 normal_file
로 나열되지 않습니다.
답변3
grep -E
필요한 일을 해야 합니다. 일부 문자는 백슬래시로 이스케이프해야 합니다. 따라서 더 많은 문자를 추가했는데 결과가 예상한 것과 다른 경우 해당 문자를 이스케이프하고 다시 시도하세요. 이것은 ...|
or
$ ls | grep -E '\s|\*|\?|\$|%'
all this.txt
all?this.txt
all*this.txt
all%this.txt
all th*s.txt
all$.txt
답변4
이는 매우 간단하며 1979년부터 Bourne Shell에서 사용할 수 있었습니다.
for i in *
do
case "$i" in
*\ *) echo blank $i;;
*\?*) echo qmark $i;;
esac
done
한 줄:
for i in *; do
case $i in
*\ *|*\?*|*\**|*\$*|*%* ) echo "Special character $i"; ;;
* ) echo "normal file $i"; ;;
esac
done
원한다면 더 많은 케이스를 추가할 수 있습니다.