почему следующая команда `find` не `ls -l` каждый файл в текущем каталоге?

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, и чтобы увидеть, передается ли ему * без кавычек, но это не может быть сделано надежно.

1
08.06.2018, 23:47
1 ответ

В обоих случаях $@расширяется вашей текущей оболочкой перед запуском find, поскольку она находится в строке -в двойных кавычках. Я предполагаю, что вы установили $1на1(и запустите printf "%s\n" "$@", чтобы увидеть текущие значения позиционных параметров ).

Чтобы проводить ваши эксперименты, как я думаю, вы должны использовать одинарные кавычки вокруг команды и двойные кавычки вокруг $@(, чтобы избежать дополнительного разбиения ); например:

find. -exec sh -c 'ls -l "$@"' sh {} \;
2
27.01.2020, 23:32

Теги

Похожие вопросы