모든 파일 이름을 반복하고 특정 문자(예: "o")가 포함된 파일 이름만 인쇄하는 bash 스크립트가 있습니다.
내가 뭘 한거지:
command=`ls -l`
for file in $command
do
if $file | grep 'o' ;
then
echo "$file"
fi
done
이것은 작동하지 않습니다. 줄에 "명령을 찾을 수 없습니다"라고 표시됩니다.
if $file | grep 'o' ;
나는 여기에서 몇 가지 다른 답변을 찾았으며 그들은 나와 동일한 작업을 수행하고 있습니다. 즉, 괄호가 없는 if 문, 동일한 구문 등입니다.
내가 무엇을 간과하고 있습니까?
답변1
$file | grep -o
file
및 값으로 지정된 명령을 실행합니다.관로grep
그러나 이것은 분명히 당신이 원하는 것이 아닙니다 .
다음을 포함하는 파일을 나열하려는 경우o
값은 실행할 명령이 아니라 file
입력 파일이라는 뜻입니다. grep
그래서 입력이 필요해요리디렉션, 파이프가 아닙니다.
if grep 'o' <"$file"
grep
명령줄에 파일 이름이 수신되지 않으면 표준 입력에서 읽습니다. 명령줄에서 파일 이름을 전달할 수도 있습니다. 이는 동일한 작업을 수행합니다.
if grep 'o' -- "$file"
큰따옴표가 사용되는 이유와 --
두 번째 접근 방식의 이유는 다음을 참조하세요.공백이나 기타 특수 문자 때문에 쉘 스크립트가 멈추는 이유는 무엇입니까?
출력을 억제하려면 옵션을 grep
사용 -q
하거나 출력을 로 리디렉션하세요 /dev/null
.
if grep -q 'o' <"$file"
또는
if grep 'o' <"$file" >/dev/null
스크립트의 또 다른 문제는 command=`ls -l`
변수를 파일 이름 목록이 아닌 command
명령의 출력으로 설정하는 것입니다. ls -l
아직도 기억한다면공백이나 기타 특수 문자 때문에 쉘 스크립트가 멈추는 이유는 무엇입니까?, 저장이 불가능하다는 것을 기억하실 것입니다목록파일 이름끈변수: 모든 파일 이름이 함께 혼합됩니다. 여기에는 더 나쁜 문제가 있습니다. 권한, 날짜 등의 정크가 있습니다. 쉘 스크립트에서 파일 이름 목록을 얻는 방법은 다음을 사용하는 것입니다.와일드카드 패턴.
for file in *
do
if grep -q 'o' <"$file"
then
echo "$file"
fi
done
이들 모두는 다음과 같습니다.
grep -l 'o' -- *
이름에 다음이 포함된 파일을 나열하려면o
이 기능은 쉘에 내장되어 있으며와일드카드 패턴. 패턴은 *o*
포함된 파일 이름과 일치하므로 o
이를 나열하려면 필요합니다.
ls -l -- *o*
--
파일 이름 중 하나가 로 시작하는 경우 이는 필수입니다. -
그렇지 않으면 ls
파일 이름이 옵션으로 해석될 수 있습니다.
이것이 사용법에 대한 학습 연습 grep
이고 파일 이름을 입력으로 전달하려는 경우 grep
해당 명령을 사용해야 합니다 echo
.
echo "$file" | grep 'o'
이 echo
명령은 일부 파일 이름을 손상시킬 수 있습니다. 안전을 유지하려면 를 사용하세요 printf
. 이에 대한 자세한 내용과 큰따옴표 사용은 다음을 참조하세요.공백이나 기타 특수 문자 때문에 쉘 스크립트가 멈추는 이유는 무엇입니까?
printf '%s\n' "$file" | grep 'o'
위에서 언급했듯이 출력은 구문 분석되지 않습니다 ls
.
for file in *
do
if printf '%s\n' "$file" | grep -q 'o'
then
printf '%s\n'
fi
done
파일 이름에 개행 문자가 포함되어 있지 않으면 .
for file in *
do
printf '%s\n' "$file" | grep 'o'
done
여기서도 루프는 의미가 없습니다.
printf '%s\n' *o*
일치하는 파일 이름을 별도의 줄에 인쇄합니다. grep
이는 정규 표현식이 필요하고 쉘의 와일드카드 패턴이 충분하지 않은 경우에만 필요합니다.
답변2
을 실행하려고 합니다 $file
. 대신 이를 에코해야 합니다.
# ...
if echo "$file" | grep 'o' ;
# ...
grep은 이미 파일 이름을 인쇄하므로 해당 이름을 음소거해야 합니다(예: grep -q 'o'
또는 grep 'o' >/dev/null
).
당신은 또한 , 당신 -l
에게 전달ls
아니요그것을하고 싶다. ls -l
일치시킬 파일 이름과 속성을 인쇄하세요.
또한 어떤 파일에서든 작동하도록 하려면 따옴표를 사용해야 할 수도 있지만 이것이 문제의 원인은 아닙니다.
추신: 다른 사람들이 지적했듯이 ls
처음에는 사용해서는 안됩니다.
답변3
ls
출력에 전혀 의존해서는 안됩니다. ls
스크립트에 사용하지 않고 인간 친화적인 출력을 표시하도록 설계되었습니다. 아래 예를 참조하세요.
for f in ./*
do
if [[ $f = *o* ]]; then
printf '%s\n' "$f"
fi
done
답변4
우선, 이것은 grep에 무언가를 파이프하는 방법이 아닙니다. 또한, 그것은일반적으로 말하면조건에서 명령을 분리하고 반환 코드만 확인하는 더 나은 형태로 간주됩니다.
다음과 같은 것이 완벽하게 작동합니다.
command=`ls -l`
for file in "$command"
do
echo "$file" | grep 'o'
if [ $? -eq 0 ]; then
echo "$file"
fi
done