xterm
использует оболочку, хранящуюся в переменной $SHELL
(, изначально установленную при входе в вашу оболочку входа ), для анализа командной строки. Итак, если вы хотите, чтобы командная строка анализировалась оболочкой zsh
, просто выполните:
SHELL=/bin/zsh xterm -e 'echo $ZSH_VERSION; sleep 4'
Или просто:
xterm -e zsh -c 'echo $ZSH_VERSION; sleep 4'
При передаче более одного аргумента xterm
не будет вызывать оболочку для разбора командной строки, он выполнит первый аргумент с его аргументами напрямую с execvp()
.
mv1 *.png
сначала расширяет шаблон подстановочных знаков *.png
в список совпадающих имен файлов, а затем передает этот список имен файлов в функцию.
Затем внутри функции $1
означает :взять первый аргумент функции, разделить его там, где он содержит пробелы, и заменить любую часть, -разделенную пробелами, которая содержит подстановочные знаки и соответствует хотя бы одному имя файла по списку совпадающих имен файлов. Звучит сложно? Так оно и есть, и такое поведение лишь изредка бывает полезным и часто проблематичным. Такое поведение при разделении и сопоставлении происходит только в том случае, если $1
встречается вне двойных кавычек, поэтому это легко исправить :используйте двойные кавычки.Всегда заключайте подстановки переменных в двойные кавычки , если только у вас нет веской причины этого не делать.
Например, если текущий каталог содержит два файла A* algorithm.png
и graph1.png
, то mv1 *.png
передает A* algorithm.png
в качестве первого аргумента функции и graph1.png
в качестве второго аргумента. Затем $1
разбивается на A*
и algorithm.png
. Шаблон A*
соответствует A* algorithm.png
, а algorithm.png
не содержит подстановочных знаков. Таким образом, функция завершается выполнением mv
с аргументами -n
, A* algorithm.png
, algorithm.png
, targetdir
и -v
. Если вы измените функцию на
function mv1 { mv -n "$1" "targetdir" -v |wc -l ;}
то он правильно переместит первый файл.
Чтобы обработать все аргументы, скажите оболочке обрабатывать все аргументы, а не только первый. Вы можете использовать "$@"
для обозначения полного списка аргументов, передаваемых функции.
function mv1 { mv -n "$@" "targetdir" -v |wc -l ;}
Это почти правильно, но по-прежнему не работает, если имя файла начинается с символа -
, потому что mv
будет рассматривать этот аргумент как опцию. Передайте --
в mv
, чтобы сказать ему «больше никаких опций после этой точки».Это очень распространенное соглашение, которое поддерживает большинство команд.
function mv1 { mv -n -v -- "$@" "targetdir" |wc -l ;}
Остается проблема, заключающаяся в том, что если mv
не удается, эта функция возвращает статус успеха, потому что статус выхода команд на левой -стороне канала игнорируется. В bash (или ksh )вы можете использовать set -o pipefail
, чтобы сбой конвейера. Обратите внимание, что установка этого параметра может привести к сбою другого кода, работающего в той же оболочке, поэтому вы должны установить его локально в функции, что возможно, начиная с bash 4.4.
function mv1 {
local -
set -o pipefail
mv -n -v -- "$@" "targetdir" | wc -l
}
В более ранних версиях параметр pipefail
был бы ненадежным, поэтому вместо этого было бы лучше явно проверить PIPESTATUS
.
function mv1 {
mv -n -v -- "$@" "targetdir" | wc -l
((!${PIPESTATUS[0] && !${PIPESTATUS[1]}}))
}
mv1 \*.png
. При взаимодействии с функциями Терминал Linux не передает звездочку непосредственно команде, а выбирает первый подходящий параметр и передает его команде.
Чтобы позволить звездочке пройти напрямую, нужно экранировать звездочку, используя обратную косую черту.
$1
— это первый аргумент функции, здесь первый файл, соответствующий *.png
. Я предполагаю, что "$@"
- это то, что вы хотите использовать вместо $1
.