Echo tail 명령이 예상치 못한 출력을 생성합니까?

Echo tail 명령이 예상치 못한 출력을 생성합니까?

이 명령은 단독으로 실행될 때 예상되는 결과를 생성합니다(crontab의 마지막 줄).

tail -n 1 /etc/crontab

그러나 결과를 파일로 보내기 위해 echo 명령의 일부로 실행하면 예상 결과와 함께 작업 디렉터리에 있는 모든 파일의 요약이 추가됩니다.

sudo bash -c 'echo $(tail -n 1 /etc/crontab) > /path/to/file'

이 명령이 추가 데이터를 생성하는 이유는 무엇입니까?

답변1

crontab 줄 *에 "언제든지"를 의미하는 별표가 하나 이상 있습니다 . 명령 대체에서 행을 바꾸면 결과는 다음과 유사합니다.

echo * * * * * cmd > /path/to/file

하지만최대명령 대체 출력에는 추가 확장이 적용되지 않습니다.경로명 확장(필드 분할과 동일):

추가 물결표 확장, 매개변수 확장, 명령 대체 또는 산술 확장을 위해 명령 대체 결과를 처리해서는 안 됩니다. 큰따옴표 안에 명령 대체가 발생하면 필드 분할 및경로명 확장교체 결과에 대해 수행하면 안 됩니다.

경로 이름 확장은 모든 항목과 일치 *.txt하는 일치하는 파일 이름(와일드카드) 목록 으로 변합니다 *. 최종 결과는 *crontab 줄에 나열된 작업 디렉터리의 모든 (숨겨지지 않은) 파일 이름을 얻는 것입니다.


게시한 코드가 더 복잡한 명령을 나타내는 경우 확장을 인용하여 이 문제를 해결할 수 있습니다.

sudo bash -c 'echo "$(tail -n 1 /etc/crontab)" > /path/to/file'

그러나 훨씬 더 즉각적인 것은 총 손실입니다 echo.

sudo bash -c 'tail -n 1 /etc/crontab > /path/to/file'

이는 원하는 작업을 수행해야 하며 더 간단합니다(유일한 다른 실질적인 차이점은 이 버전에서 발생하는 필드 분할을 생략하므로 공간이 축소되지 않는다는 것입니다).

답변2

다음 파일이 포함된 디렉터리를 고려해 보겠습니다.

$ ls
crontab  file1  file2  file3
$ cat crontab
f*

이제 tail 명령을 실행해 보겠습니다.

$ tail -n 1 crontab
f*

crontab위는 우리가 기대하는 마지막 줄 입니다. 하지만:

$ echo $(tail -n 1 crontab)
file1 file2 file3

큰따옴표는 이 문제를 해결합니다.

$ echo "$(tail -n 1 crontab)"
f*

큰따옴표가 없으면 결과는 다음과 같습니다.명령 대체쉘로 확장되었습니다. 확장 중 하나는경로명 확장. 위의 경우 이는 f*일치하도록 확장하는 것을 의미합니다 f.

쉘 확장을 명시적으로 원하지 않는 한, 모든 쉘 변수 및/또는 명령 대체를 큰따옴표로 묶으십시오.

답변3

*globbing shell 메커니즘은 로컬 파일로 확장됩니다 .

crontab 줄에는 *as 자리 표시자가 있을 수 있습니다.

예를 들어, crontab의 이 행은 일요일 오전 7시 47분에 실행되며 첫 번째 별은 날짜를 나타내고 두 번째 별은 월을 나타냅니다.

47  7 * * 0 /run/on/sunday

그럼 당신 tail과 문제

echo 47  7 * * 0 /run/on/sunday

*로컬 파일로 확장됩니다 .

관련 정보