zsh
по умолчанию запрашивает подтверждение, когда вы пытаетесь выполнить любую команду под названием rm
с *
в виде целого слова в командной строке (эта возможность унаследована от tcsh
, хотя в tcsh
она не включена по умолчанию).
$ rm -rf *
zsh: sure you want to delete all the files in / [yn]?
Если вы вынуждены использовать bash, то в последних версиях bash
вы можете сделать нечто похожее, используя extdebug
и ловушку DEBUG
:
shopt -s extdebug
check_for_rm_star() {
case $1 in
(rm*[\ /]"* "* | rm*[\ /]\*)
read -p "check_for_rm_star: Are you sure? " -n1 answer < /dev/tty > /dev/tty
echo > /dev/tty
[[ $answer == [yY] ]]
esac
}
trap 'check_for_rm_star "$BASH_COMMAND"' DEBUG
Это упрощенный вариант, который будет работать для rm *
и наиболее распространенных случаев, но не для rm "*"
или /bin/rm *
или : $(rm *)
, но вы поняли идею. В идеале, нам нужно было бы разобрать $BASH_COMMAND
так же, как это делает shell, чтобы увидеть, расширяется ли первый аргумент до rm
или */rm
, и чтобы увидеть, передается ли ему *
без кавычек, но это не может быть сделано надежно.
В обоих случаях $@
расширяется вашей текущей оболочкой перед запуском find
, поскольку она находится в строке -в двойных кавычках. Я предполагаю, что вы установили $1
на1
(и запустите printf "%s\n" "$@"
, чтобы увидеть текущие значения позиционных параметров ).
Чтобы проводить ваши эксперименты, как я думаю, вы должны использовать одинарные кавычки вокруг команды и двойные кавычки вокруг $@
(, чтобы избежать дополнительного разбиения ); например:
find. -exec sh -c 'ls -l "$@"' sh {} \;