파일 확장자가 .java인지 확인하는 방법은 무엇입니까?
지금까지 나는 다음을 가지고 있습니다 :
for javaFile in *.java ; do
{
echo "The file $javaFile has : " >> ~/Desktop/externalServers.txt
grep -E '^[^/]{2}.*http' $javaFile >> ~/Desktop/externalServers.txt
grep -E '^[^/]{2}.*ftp' $javaFile >> ~/Desktop/externalServers.txt
echo "----------------------------------------" >> ~/Desktop/externalServers.txt
sed -e "s/[[:space:]]\+/ /g" ~/Desktop/externalServers.txt >> ~/Desktop/externalServersTemp.txt
rm ~/Desktop/externalServers.txt
mv ~/Desktop/externalServersTemp.txt ~/Desktop/externalServers.txt
sed 's/^\n//' ~/Desktop/externalServers.txt >> ~/Desktop/externalServersTemp.txt
rm ~/Desktop/externalServers.txt
mv ~/Desktop/externalServersTemp.txt ~/Desktop/externalServers.txt
} done
하지만 이 작업을 수행할 때마다 다음과 같은 오류가 발생합니다.
grep: *.java: 해당 파일이나 디렉터리가 없습니다.
기본적으로 먼저 폴더에 .java 유형 파일이 있는지 확인한 다음 스크립트 실행을 계속 진행하고 싶습니다.
답변1
Bash에서는 다음을 사용하십시오.
shopt -s nullglob
for pdfFile in *.java;do
# your code goes here
done
이 구문은 Bourne과 같은 쉘에서 작동합니다. 이 nullglob
옵션은 bash에만 적용됩니다. 사용한 중괄호( )는 {}
C 스타일 쉘용입니다.
shopt -s nullglob
이 nullglob
옵션이 설정되면 기본적으로 일치하지 않는 glob을 빈 문자열로 확장해야 한다고 Bash에 알립니다. 기본적으로 *.java
일치하는 항목을 찾을 수 없으면 자체적으로 확장됩니다(별표는 유지됨).
답변2
내가 작성한 스크립트는 다음과 같습니다.
set -- *.java
test -e "$1" && {
fortyequals=$(printf '%040d\n' | tr 0 \=)
for javaFile do
printf '%s\nIn file: %s\n%s\n' \
$fortyequals "$javaFile" $fortyequals
grep -E '^[^/]{2}.*(ftp|http)' "$javaFile"
done
} >>~/Desktop/externalservers.txt
이미 제공된 솔루션은 다음과 같습니다.불필요하게쉘 특정. 이식 가능한 구문을 사용하면 동일한 효과를 얻을 수 있습니다. 이렇게 하면 장기적으로 기억하기가 덜하고 더욱 강력해진다는 추가 이점이 있습니다. 예:
set -- *.java
test -e "$1" &&
for javaFile do
# ...iterate on $javaFile here...
done
$javaFile
또 다른 장점은 다음 루프의 최신 값을 유지할 뿐만 아니라모두$javaFile
우리가 한때 가졌던 가치 $@
. 이를 통해 다음이 가능해집니다.
...
done
echo "The previous for loop processed $# files."
echo "The first file processed was:"
printf "///\t'%s'\t///\n" "$1"
echo "The last file processed was:"
printf "///\t'%s'\t///\n" "$javaFile"
echo 'All files processed in the for loop were:'
printf "///\t'%s'\t///\n" "$@"
{
곱슬머리를 정말 좋아한다면 , 곱슬 }
머리에도 사용할 수 있습니다.bash
(꼭 필요한 것은 아니지만)- 하지만 두 껍질을 분리해야 합니다.예약어 }
그리고 done
좋아해요:
for ... do {
...
} ; done
내 제안은 블록 전체를 울타리로 막는 것입니다.에 대한루프 for
및 수행하는 모든 후처리 - 공상적으로는 다음에 따라 다릅니다.&&
예약어좋다:
set -- *.java
test -e "$1" && {
for ... done
# ...further processing on $@...
}
돌이켜보면 정규식으로도 큰 도움이 될 수 있었을 거라 생각합니다... 다음 단어가 포함된 행을 찾고 있는 것 같습니다.http그리고/또는파일 전송 프로토콜그렇게아니요두 개로 시작하다//.
나머지는 혼자 하는 일이라고 생각해요 grep
. 빈 줄을 지우려고 하는 것 같지만, 내가 상상하는 것처럼 이러한 빈 줄은 처음에 파일에 반복적으로 추가된 결과일 뿐입니다.
따라서 for
루프의 출력을 출력 파일에 직접 쓸 수 있으므로 ~/Desktop/externalservers.txt
루프가 완료될 때까지 쓰기 설명자가 유지되므로 빈 줄을 쓰지 않아도 됩니다. 아마도 다음과 같습니다:
for ... done >>outfile
또는
{ grouped ; command ; list ; } >>outfile
적어도 이 문장이 원하는 효과를 얻지 못할 수도 있다는 점은 말씀드릴 수 있습니다.
sed 's/^\n//' $file
sed
ewline으로 구분 됩니다 . 줄의 첫 번째 문자 로 ewline을 \n
만날 수 없습니다 . 다양한 방법으로 패턴 공간 에 줄눈을 넣을 수 있지만 , 일부 처리 없이는 절대 넣을 수 없습니다.\n
^
\n
sed
답변3
샘플 코드의 또 다른 문제는 일반적으로 원하는 것입니다.모든 반복자에 큰따옴표를 사용하세요.for 루프에서 사용할 때.
귀하의 코드:
for javaFile in *.java ;
{
echo "The file $javaFile has : " >> ~/Desktop/externalServers.txt
grep -E '^[^/]{2}.*http' $javaFile >> ~/Desktop/externalServers.txt
grep -E '^[^/]{2}.*ftp' $javaFile >> ~/Desktop/externalServers.txt
해야 한다:
for javaFile in *.java ; do
echo "The file $javaFile has : " >> ~/Desktop/externalServers.txt
grep -E '^[^/]{2}.*http' "$javaFile" >> ~/Desktop/externalServers.txt
grep -E '^[^/]{2}.*ftp' "$javaFile" >> ~/Desktop/externalServers.txt
답변4
Joseph의 nullglob
방법이 가장 우아하지만, 이를 사용하고 싶지 않거나 사용할 수 없는 경우(예: bash가 아닌 쉘 또는 이전 bash 버전) 이 작업을 수행할 수도 있습니다(파일 이름에 개행 문자가 포함되어 있지 않다고 가정).
file="~/Desktop/externalServers.txt"
while IFS= read -r javaFile
do
echo "The file $javaFile has : " >> "$file"
grep -E '^[^/]{2}.*http' "$javaFile" >> "$file"
grep -E '^[^/]{2}.*ftp' "$javaFile" >> "$file"
echo "----------------------------------------" >> "$file"
## The -i flag enables in-place editing so you don't need
## to fiddle about with temp files.
sed -i -e "s/[[:space:]]\+/ /g" "$file"
sed -i -n '/[^[:space:]]/p' "$file"
done < <(find . -maxdepth 1 -name '*.java')
공백이 포함된 파일 이름을 적절하게 처리할 수 있도록 입력 필드 구분 기호를 비워 두십시오 IFS=
. 옵션은 백슬래시를 특별히 처리하지 않음을 -r
나타냅니다 read
(파일 이름에 백슬래시가 포함될 수 있는 경우). 이 <(command)
구조는프로세스 교체그리고 한 명령의 출력을 다른 명령의 입력으로 전달하는 방법입니다.
$file
출력 파일 이름을 변경하려는 경우 모든 줄을 편집할 필요가 없도록 이 변수를 도입했습니다 .
나는 -i
sed 플래그를 사용했는데, 이를 통해 원본 파일을 편집할 수 있고 임시 파일이 필요하지 않습니다. 또한 이 작업을 수행할 이유가 없으며 rm foo.txt; mv bar.txt foo.txt
언제든지 수행할 수 mv bar.txt foo.txt
있으며 대상 파일을 덮어쓰게 됩니다. 이제 이 명령이 무엇을 해야 할지 모르겠습니다.
sed 's/^\n//' ~/Desktop/externalServers.txt >> ~/Desktop/externalServersTemp.txt
빈 줄을 제거하고 싶었지만 작동하지 않아서 위에서 변경했습니다.
sed -i -n '/[^[:space:]]/p' ~/Desktop/externalServers.txt
-n
모든 줄을 인쇄하는 sed의 기본 동작을 억제합니다 . /[^[:space:]]/
이는 공백이 아닌 문자와 일치하는 모든 줄과 일치하며 p
끝에 's'는 해당 줄과 해당 줄만 인쇄됨을 의미합니다. 이것이 명령으로 수행하려는 작업이 아닌 경우 sed
알려주시면 필요에 따라 편집하겠습니다.