다른 명령 후에 명령이 실행되지 않도록 방지

다른 명령 후에 명령이 실행되지 않도록 방지

나는 내가 만들려고 하는 잠재적인 오류에 대해 쉘이 나에게 경고해주기를 원합니다.

. 이후에 명령이 cmd2실행되지 않도록 하려면 어떻게 해야 합니까?cmd1

예를 들어:

$ tar tf file.tar
$ rm !$

여기서는 내용을 추출하는 대신 파일을 나열했다는 사실을 잊어버렸습니다.

저는 이전 명령의 이름과 반환 값, 그리고 현재 명령을 기반으로 선택하는 일반적인 솔루션을 찾고 있습니다.

답변1

shopt -s histverifyBash에서는 기록이 한 단계로 확장 및 실행되는 것을 중지하도록 설정할 수 있습니다 . 여기서 위의 내용은 을 처음 누를 때 $ rm !$로 확장되어 다시 눌러 실행하기 전에 확인하거나 편집할 수 있습니다 . 보다 일반적인 해결책은 다음과 같습니다.$ rm file.tarEnterEnter
"내 말대로 하세요"당신의 의도를 추측하는 프로그램이 필요합니다.

답변2

일반적인 답변으로 많은 것을 요구하고 계시지만, 어느 정도는 비교적 쉽게 할 수 있을 것입니다.

하지만 에는 bash이 문제를 해결하는 데 도움이 될 수 있는 최소한 두 가지 일반적인 메커니즘이 있습니다. PROMPT_COMMAND 변수를 설정할 수 있으며 이는 프롬프트에서 실행한 후에 실행됩니다.

$ PROMPT_COMMAND='echo BOFH says hi!'
BOFH says hi!
$ man man
BOFH says hi!
$

이를 사용하여 마지막으로 입력한 명령을 저장한 다음 다시 읽을 수 있으므로 나중에 사용하기 위해 메모리에 저장할 수 있습니다(이 경우 기록 확장은 작동하지 않습니다).

$ PROMPT_COMMAND='history -a; tail -n1 ~/.bash_history'
PROMPT_COMMAND='history -a; tail -n1 ~/.bash_history'
$ wc < test.sh | grep .
 5 11 63
wc < test.sh | grep .

이제 완전히 당신에게 달려 있는 논리 부분이 나옵니다. 질문의 예를 방지하기 위해 매우 단순한 논리를 사용합시다. 기억해야 할 점은 bash 기능이 여전히 거기에서 작동하므로 모든 것을 한 줄, 단일 변수에 넣을 필요가 없다는 것입니다.

$ # define the logic check
$ checkSanity() { grep -q "tar  *[tf][[:alpha:]]*[tf] " <<< "$@" && echo "be careful, don't delete this"; }
checkSanity() { grep -q "tar  *[tf][[:alpha:]]*[tf] " <<< "$@" && echo "be careful, don't delete this"; }
$ # feed it the last command
$ PROMPT_COMMAND='history -a; last=$(tail -n1 ~/.bash_history); checkSanity "$last"'
$ # simple test
$ tar tf test.sh 2>/dev/null 
be careful, don't delete this
$ tar xf test.sh 2>/dev/null 
$

물론 이 접근 방식은 PEBKAC를 방지하는 데 유용 sleep 3하지만(특히 끝에 추가하는 경우) 다음 명령을 자체적으로 중단할 수는 없습니다.

그렇다면정말원하는 것은 미리 실행되므로 DEBUG신호(예: )를 트랩합니다. trap 'echo "I am not deterministic, haha"' DEBUG출력/작업이 두 배가 되므로 이 두 가지 접근 방식을 결합할 때는 주의하세요.

$ df
/.../
$ trap 'tail -n1 ~/.bash_history' DEBUG
df
df
trap 'tail -n1 ~/.bash_history' DEBUG
trap 'tail -n1 ~/.bash_history' DEBUG

extdebug트랩이 명령을 중단하도록 하려면 ( ) 을 활성화해야 합니다 shopt -s extdebug. 또한 기록을 지속적으로 저장하고 다시 읽을 필요는 없지만 검사 $BASH_COMMAND하여 실행하려는 명령을 가져올 수 있습니다. 그런 다음 논리 검사기가 잘못된 것을 감지하면 1을 반환하고 그렇지 않으면 0을 반환하는지 확인하면 됩니다.

          extdebug
                  If set, behavior intended for use by debuggers is enabled:
    /.../
                  2.     If  the command run by the DEBUG trap returns a non-zero value, the next
                         command is skipped and not executed.


$ checkSanity() { if grep -q "tar  *[tf][[:alpha:]]*[tf] " <<< "$1"; then  echo "be careful, don't delete this"; return 1; fi; }
$ trap 'checkSanity "$BASH_COMMAND"' DEBUG
$ # simple test
$ tar tf test.sh 2>/dev/null 
be careful, don't delete this
$ tar xf test.sh 2>/dev/null 
$

답변3

이 경우 rm명령의 오류 경고를 통해 이점을 얻을 수 있습니다.

쉘 초기화 스크립트( bash, so 가정)에서 또는 에 ~/.bashrc별칭을 지정할 수 있습니다 .rm-i-I

alias rm="rm -i"

에서man 1 rm

   -i     prompt before every removal

   -I     prompt once before removing more than three files, or when
          removing recursively.  Less intrusive than -i, while still
          giving protection against most mistakes

"나 자신으로부터 시스템을 어떻게 보호합니까?"라는 보다 일반적인 질문은전에 논의한. 간단히 말해서,당신이하고있는 일에주의를 기울이십시오, 필요한 경우에만 명령을 실행합니다 root.

답변4

귀하의 구체적인 경우에는 다음을 수행합니다.

tar tf file.tar
if [ -f file ]; then   # Assuming you meant to extract a file
  rm -f file.tar
else
  echo "file is missing. Command failed."
fi

오류를 확인하고 첫 번째 명령이 성공한 경우에만 다음 명령을 실행하려는 경우

some_command && another_command

특정 경우에는 원하는 작업을 수행하지 않았더라도 오류가 발생하지 않았으므로 두 번째 명령이 계속 실행됩니다.

관련 정보