TL/DR:저는 솔라리스 10에서 작업하고 있습니다. 명령 이 있는데 ls ... | egrep ...
그 명령이 어떤 결과를 출력하는지 알아야 합니다. | wc -c
끝에 하나를 추가 할 수 있지만 출력이 아닌 종료 코드에 결과(0 또는 0이 아님)가 필요합니다. 그리고 저는 그것을 사용할 수 없습니다 if
. 그것은 bash 스크립트가 아니며, 하나의 명령만 실행할 수 있습니다.
긴 버전: 저는 Solaris 10 시스템에서 오래된 로그 파일을 압축하고 삭제하기 위한 유지 관리 절차를 작성 중입니다. 지정된 경로 내의 모든 .log 또는 .xml 파일을 확인하고, 지정된 달에 마지막으로 수정된 파일을 가져오고, 해당 파일로 .tar를 생성한 다음 원본 파일을 삭제합니다.
ls -Egopqt /path/ | egrep -i '2016-10-[0123][0-9] .*(\.log$|\.xml$)' | awk '{ print $7 }'
| xargs tar -cvf target.tar
파일 삭제도 같은 방식으로 작동합니다. 마지막 부분을 다음으로 바꾸면 됩니다.| xargs -i rm {}
너무 복잡하게 생각할 수도 있지만효과가있다. 파일이 없으면특정 달에 해당하는 경우 오류 메시지가 표시됩니다 tar: Missing filenames
. tar를 생성하기 전에 어떻게 확인하나요? 나는 이런 것을 생각했다.wc를 사용하여 출력이 있는지 확인하십시오.:
ls ... | egrep ... | wc -c
0
파일이 없으면 올바르게 출력되고, 그렇지 않으면 다른 숫자가 출력됩니다. 문제는 다음과 같습니다출력은 없고 종료 코드만 표시됩니다.(오류가 없으므로 항상 0입니다.) Bash 스크립트에서 이 작업을 수행하는 대신 Siebel CRM을 사용하고 있습니다. 명령을 생성하고 다음을 사용하여 실행하는 javascript 함수가 있습니다.도서관 시스템수신 전화. 내가 볼 수 있는 유일한 것은 종료 코드입니다. 0
정상을 의미하고, 0이 아닌 것은 오류를 의미합니다("0이 아닌"이 아닌 실제 숫자가 보입니다).
이전에는 다음과 같은 사항을 확인해야 하는 비슷한 요구 사항이 있었습니다.하나의파일이 존재하는지 여부이 답변이 작업을 수행하는 데 도움이 되었습니다.
[ -f filename ] && exit 111 || exit 0
파일 이름이 존재하는지 여부에 따라 111
또는를 성공적으로 얻습니다 . 하지만 명령으로 작동하게 0
할 수는 없습니다 . ls ... | egrep ... | wc
나는 사용해 보았습니다.이 문법:
[[ $( ls -Egopq /path/ | egrep -i ... | wc -c ) -ne 0 ]] && exit 111 || exit 0
하지만 저는 항상 코드 2로 종료합니다. 파일이 있는지 없는지는 중요하지 않습니다. 내가 뭘 잘못했나요?
추신: 검사를 수행하고, 간단한 방법을 사용하여 if
출력을 비교하고, 원하는 종료 코드를 반환하는 작은 쉘 스크립트를 작성할 수 있다는 것을 알고 있습니다. 또, 나는 실제로할 수 있는명령의 출력에 액세스하려면 이를 javascript로 리디렉션한 > tempfile
다음 Siebel에서 읽으면 됩니다. 그러나 불필요한(임시 또는 영구) 파일 생성을 피하려고 하기 때문에 두 옵션을 모두 피하는 것이 좋습니다.
답변1
egrep
일치하는 행이 없으면 0이 아닌 값을 반환합니다.
답변2
xargs
매뉴얼 에서 :
--no-run-if-empty
-r If the standard input does not contain any nonblanks, do not run the command.
Normally, the command is run once even if there is no input. This option is a GNU extension.
... | xargs -r tar -cvf target.tar
이렇게 하면 문제가 해결될 것 같습니다 !
답변3
이 ls
명령은 사용자에게 정보를 제공하기 위해 미세 조정되었습니다. 즉, 안정적으로 구문 분석할 수 있는 출력을 생성하는 데는 적합하지 않습니다.
대신 사용을 고려해보세요 find
. 즉, 당신도 그것을 사용하지 않을 수 있다는 뜻입니다 grep
.
예를 들어, .DeleteMe
이름이 일주일 이상으로 끝나는 모든 파일을 삭제하려면 다음을 수행하십시오.
find /path -name '*.DeleteMe' \
-mtime +6 \
-exec rm -f -- {} +
그것이 무엇을 할 것인지 보려면 -exec rm
로 바꾸십시오 -exec echo rm
.
(*1) 과 관련된 다른 방법과 달리 이 방법의 장점은 xargs
이상한 문자가 포함된 파일 이름을 만나도 이상한 일을 하지 않는다는 것입니다.
다음과 같은 경우 추가 조치를 취하고 싶은 경우:아니요파일을 일치시키고 파일 목록을 임시 파일에 쓴 다음 파일이 비어 있는지 확인하는 것은 매우 간단합니다.
find /path -name '*.DeleteMe' \
-mtime +6 \
-exec rm -f -- {} + \
-print > list_of_files$$
if ! [ -s list_of_files$$ ] ; then
echo There were no matching files
fi
rm -f list_of_files$$
첫 번째 파일 이전에 몇 가지 추가 작업을 수행해야 하는 경우
find /path -name '*.DeleteMe' \
-mtime +6 \
-exec sh -c '
o=$0 # at_least_one$$ from the outer shell
[ -e $o ] || do_before_stuff
> $o
for f do
do_something with "$f"
done
' at_least_one$$ {} +
if [ -e at_least_one$$ ] ; then
do_after_stuff
else
do_no_files_stuff
fi
rm -f at_least_one$$
물론 이는 단순화된 예입니다. 복잡한 작업을 수행하는 경우 sh -c 'code here'
스크립트를 작성하고 대신 호출하는 것을 고려하십시오.
귀하의 구체적인 질문에 대해서는 다음과 같이 쓸 것입니다.
find /path/ -name '2016-10-[0123][0-9]*' \
\( -name '*.log' -o -name '*.xml' \) \
-exec tar -cvf target.tar {} +
나는 이것이 지금까지 보여진 다른 모든 방법과 동일한 실패 모드를 가지고 있다는 것을 알았습니다. 파일 목록이 명령줄에 비해 너무 길면 tar
반복적으로 호출되어 마지막 몇 개의 파일만 포함하는 타르볼이 생성될 수 있습니다.
이 문제를 해결하려면 다음을 사용하는 것이 좋습니다 cpio
.
find /path/ -name '2016-10-[0123][0-9]*' \
\( -name '*.log' -o \
-name '*.xml' \) \
-print |
cpio -o > target.cpio.trial
if [ -s target.cpio.trial ]
then mv target.cpio.trial target.cpio
else rm target.cpio.trial
fi
일부 버전에서는 cpio
-H를 지원합니다.체재, 이는 다음을 사용하여 추출할 수 있는 tarball을 작성하도록 지시할 수 있음을 의미합니다 . 그렇지 않으면 필요할 때 파일을 추출 tar
해야 합니다 (귀하의 버전이 cpio 형식의 아카이브를 이해하지 않는 한).cpio
tar
(각주 *1: 좋습니다. GNU find 및 GNU xargs가 있다면 이는 GNU find 및 GNU xargs find ... -print0 | xargs -0r cmd ...
만큼 안정적 find ... -exec cmd {} +
이지만, 이것이 있다면 다른 더 나은 옵션이 있습니다.)