스크립트를 실행할 때 스크립트에서 셸 별칭을 이스케이프하는 것이 유용합니까?

스크립트를 실행할 때 스크립트에서 셸 별칭을 이스케이프하는 것이 유용합니까?

bash소스가 아니고 작동하는 쉘 스크립트에서 이스케이프 별칭이 의미가 있습니까?


가장 간단한 경우를 고려하면 많은 사용자가 ls기능을 재정의하기 위해 (in 또는)를 사용합니다. 예를 들면 다음과 같습니다.alias.bashrc.bash_aliases

alias ls='\ls --color=auto --group-directories-first'

그런 다음 다음과 같은 함수가 포함된 쉘 스크립트를 호출한다고 가정해 보겠습니다.

list_sata_devices ()
{
    \ls -1 /dev/sd?
}

눈치채셨듯이 강제로원래의 ls\ls, 그런데 이것이 필요한지 궁금합니다.


물론 없이도 작성할 수 있습니다 ls. 예를 들면 다음과 같습니다.

list_sata_devices ()
{
    printf '%s\n' /dev/sd?
}

하지만 어떤 차이가 있을지는 여전히 망설여집니다.

답변1

alias ls='\ls --color=auto --group-directories-first'

백슬래시가 필요하지 않습니다.쉘은 그런 사소한 루프에 갇히지 않습니다.:

대체 텍스트의 첫 번째 단어는 별칭이 있는지 테스트되지만 확장되는 단어와 동일한 별칭을 가진 단어는 다시 확장되지 않습니다.


그런 다음 다음과 같은 함수가 포함된 쉘 스크립트를 호출한다고 가정해 보겠습니다.

list_sata_devices ()
{
    \ls -1 /dev/sd?
}

쉘 스크립트, 즉 비대화형 쉘인 경우,그런 다음 별칭은 기본적으로 비활성화됩니다.:

쉘이 비대화형인 경우, Shopt를 사용하여 Expand_aliases 쉘 옵션을 설정하지 않으면 별칭은 확장되지 않습니다(Shopt 내장 참조).

스크립트는 이를 명시적으로 활성화해야 합니다(shopt -s expand_aliases) 설사 어떤 이유로든 대화형 쉘에 설정된 별칭을 상속하지 않으며 비대화형 쉘은 예를 들어 읽지 않으므로 .bashrc거기에서 가져오지 않습니다.비대화형 쉘은 다음과 같은 파일을 읽습니다.$BASH_ENV그래도 거기에 별칭을 설정하지 않을 수도 있습니다.

따라서 여기서도 백슬래시가 필요하지 않습니다.


list_sata_devices ()
{
    printf '%s\n' /dev/sd?
}

음, 다른 명령입니다. 실제로는 큰 효과가 없지만 ls터미널에 인쇄하면 일부 특수 문자가 다르게 처리될 수 있습니다.

아무튼 배쉬할 수 있는 내보내기 및 상속 기능환경에 따라 스크립트가 엉망이 될 수 있지만 일반적으로 실수로 그런 일을 하지는 않을 것입니다.

답변2

귀하의 컨텍스트는 호출 셸에서 스크립트를 가져오는 대신 해당 환경에서 스크립트를 실행하려는 것과 같습니다.
이 경우 이름이 이전에 별칭으로 지정되었더라도 스크립트에서 명령 이름을 이스케이프할 필요가 없습니다.

별칭 정의가 포함된 파일을 얻지 못한 경우 별칭은 스크립팅 환경으로 전송되지 않습니다.

스크립트는 대화형 셸이 아니므로 스크립트의 별칭 정의의 유용성은 주로 대화형 컨텍스트에서 편의를 위한 것이기 때문에 의심스럽습니다. (희망적으로) 기억하기 쉬운 약어인 cmd 별칭은 기본적으로 인간과 기계 사이의 상호 작용을 단순화합니다("긴 명령을 많이 기억하고 터미널 창에 입력할 필요가 없도록 해줍니다" 참조).

따라서 나는 일반적으로 여러 가지 이유로 스크립트에서 미리 정의된 별칭을 사용하지 않습니다. (i) 스크립트 가독성, (ii) 스크립트를 정의하기 위해 외부 별칭을 사용하지 않고도 스크립트와 해당 기능에 대한 모든 제어를 유지합니다. 포함된 것과 포함되지 않은 것 포함됩니다. 당신의 스크립트. 다른 곳에 정의된 별칭을 기반으로 스크립트를 작성한 다음 이전 스크립트가 실제로 이에 의존했다는 사실을 기억하지 못한 채 몇 달 또는 몇 주 후에 해당 별칭 정의를 수정한다고 상상해 보십시오. 기본적으로 별칭은 자식에서 실행되는 스크립트로 전송되지 않습니다. 그것은 좋은 일입니다. 껍데기.

또한 man bash함수 내부에서 별칭은 함수를 읽고 사용할 수 있게 된 후에만 확장됩니다.뒤쪽에기능이 실행됩니다. 따라서 실제로 스크립트에서 별칭을 정의하는 경우(보통은 정의하지 않지만 특별한 사용 사례가 있을 수 있음) 가장 좋은 위치는 다른 줄에 있는 것입니다.이상해당 별칭을 사용하는 함수 또는 cmd(여기서는 셸에서 명령으로 실행되는 함수를 고려하세요).

마지막으로 스크립팅과 관련이 없지만 상단에 있는 @muru의 설명은 완전히 유효하며 Bash 매뉴얼에서 찾을 수 있습니다. 별칭 확장에 자체 이름이 포함된 경우 확장에 해당 별칭 이름이 발생해도 해당 이름의 새 확장이 발생하지 않습니다. 이로 인해 무한 재귀가 발생합니다. 따라서 다음을 볼 수 있지만 작성할 필요는 없습니다: alias ls='\ls --color=auto --group-directories-first'. 대신 다음과 같이 작성하세요: alias ls='ls --color=auto --group-directories-first'.

그러나 이전 별칭을 이스케이프하는 것이 유용할 수 있지만 다음과 같은 상황에서는 다릅니다.

  alias ls='ls -A --color=auto --group-directories-first'
  alias ll='\ls -l --color=auto'

ls위의 경우 별칭 에서 이스케이프 하지 않으면 ll별칭을 정의하는 첫 번째 줄에 정의된 플래그와 옵션이 포함되며 ls, 이는 원할 수도 있고 원하지 않을 수도 있습니다. 이는 별칭 연결은 괜찮지만 재귀는 그렇지 않다는 것을 알려줍니다.


편집하다:ls -1 <foo*>와 의 차이점에 대한 마지막 질문에 답하려면 다음과 같이 하십시오 printf '%s\n <foo*>.

예를 들어, Gnu Bash v5.1.4를 실행하는 특정 x86_64 시스템에서:

 $ time for i in $(seq 10000); do \ls -1 /dev/sd* 1> /dev/null; done
 real    0m17.420s
 user    0m10.910ss
 sys     0m7.598s

 $ time for i in $(seq 10000); do printf '%s\n' /dev/sd*  1> /dev/null; done
 real    0m0.574s
 user    0m0.285s
 sys     0m0.287s

ls내장되어 있어도 실행하는데 시간이 많이 걸리기 때문에어떻게 작동하나요?. lstat()파일 권한이 관련될 때 사용된다는 사실 외에는 구현의 세부 사항을 잘 알지 못합니다.

관련 정보