이 명령은 단독으로 실행될 때 예상되는 결과를 생성합니다(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
*
로컬 파일로 확장됩니다 .