Только поставив альтернативу sed
. Это напечатает последний столбец из строки, разделенной пробелами.
sed 's/.*[[:space:]]\(.*\)$/\1/'
Я протестировал его для случаев, когда a.resolvers.level3.net
является единственной строкой в переменной $name, и она работает.
$ echo "$name"
1.2.2.4.in-addr.arpa domain name pointer a.resolvers.level3.net
$
$ echo "$name"|sed 's/.*[[:space:]]\(.*\)$/\1/'
a.resolvers.level3.net
$
$ name="a.resolvers.level3.net"
$ echo "$name"|sed 's/.*[[:space:]]\(.*\)$/\1/'
a.resolvers.level3.net
$
Псевдоним не поддерживает такие операнды, как $@, $1, $2 и т. д.
Ваша команда
alias mvaf="mv $@ && cd $_"
равно mv ' ' && cd $_
, потому что $@
не распознается псевдонимом так, как вы ожидаете.
Это легко доказать следующим образом:
$ alias mvaf='echo "Part 1:" $@ && echo "Part 2: " $_'
$ mvaf file66 /tmp/
Part 1:
Part 2: Part 1: file66 /tmp/
#Part 2 includes the previous executed command (echo "Part 1:" $@) & the text sent after alias name
$ alias mvaf='echo "Part 1:" $@;echo "Part 2: "'
$ mvaf file66 /tmp/
Part 1:
Part 2: file66 /tmp/
С другой стороны, это работает, но не из-за $@
$ alias mvaf='echo "mv $@"'
$ mvaf file66 /tmp/
mv file66 /tmp/
$ alias mvaf='echo "mv"'
$ mvaf file66 /tmp/
mv file66 /tmp/
Псевдоним — это своего рода простая замена.
Псевдоним aa='command1;command2'
, при вызове как aa sometext
равноcommand1;command2 sometext
Чтобы заставить это работать, вам нужно сделать это с помощью функции. Bash не поощряет использование псевдонимов и поощряет использование функций для таких заданий. Вы можете прикрепить эту функцию к вашему файлу профиля bash, и эта функция может быть вызвана по имени прямо из вашего терминала, как если бы вы делали это с любым псевдонимом:
mvcd() { mv "$1" "$2" && cd "$2"; }
Связывание команд mv
и cd
с &&
здесь важно, так как &&
гарантирует, что вторая команда cd
будет выполнена только в том случае, если предыдущая команда mv
была успешной.
В качестве альтернативы, как уже было сказано в ссылке принятого ответа на ваш вопрос , вы можете сделать что-то вроде
mvf() { mv "$@" && goto "$_"; }
goto() { [ -d "$1" ] && cd "$1" || cd "$(dirname "$1")"; }
Будьте осторожны с разбиением слов bash.Чтобы такая функция работала правильно, вам нужно вставить двойные кавычки при вызове функции, если файл, который вы собираетесь переместить, или каталог, в который файл будет отправлен, содержат пробел в своем имени.
$ mvcd() { echo "1=$1";echo "2=$2";echo "3=$3";echo "4=$4"; }
$ mvcd spaced file1 /spaced directory/
1=spaced
2=file1
3=/spaced
4=directory/
$ mvcd "spaced file1" "/spaced directory/"
1=spaced file1
2=/spaced directory/
3=
4=
Как написал @Deathgrip в комментарии,
не существует механизма для использования аргументов в замещающем тексте. Если требуются аргументы, следует использовать функцию оболочки (см. ФУНКЦИИ ниже).
Как работают псевдонимы?
Давайте подумаем, что произойдет, если вы введете следующие две строки в командной строке:
$ alias word1="echo example"
$ word1 word2 word3
При выполнении первой команды bash
помнит, что всякий раз, когда word1
является первым словом любой команды, он должен заменить его на echo example
. Увидев вторую команду, он прежде всего выполняет подстановку самым тупым (самым простым) способом — из этого ввода создает команду echo example word2 word3
. Поэтому он повторяет пример слово2 слово3
.
Что происходит с вашим псевдонимом?
Когда он видит mfav one two
, он просто оценивает mv $@ && cd $_ one two
. Поскольку $@
пусто (попробуйте echo $@
в консоли), mv
не работает. cd
также не работает, так как получает больше аргументов, чем один.
Примечание: я слишком упростил запись, что псевдоним заменяет только первое слово. В случае нарушения этого правила см. мой другой ответ .
Все остальные ответы объясняют, почему псевдоним не работает, а ответ Джорджа Василиу дает альтернативную функцию, которая выполняет эту работу.
Однако я хотел развить этот ответ, чтобы сделать его более надежным. В настоящее время функция
mvcd() { mv "$1" "$2" && cd "$2"; }
не будет работать, если целью является файл. Чтобы исправить это, мы можем использовать нотацию подстроки переменной bash:
mvcd() { mv "$1" "$2" && [[ -d $2 ]] && cd $2 || cd ${2%/*}; }
Чтобы увидеть, что здесь происходит, давайте запишем это в немного более читаемом формате:
mvcd () {
mv "$1" "$2"; # Do the move
if [[ -d $2 ]] # Check if arg $2 is a dir
then
cd $2; # if it is, cd into it
else
cd ${2%/*}; # else remove the filename and cd
fi;
}
Мы проверяем, является ли пункт назначения каталогом[1] - и если это так, мы просто cd в него. Если это не так, то мы подстроим второй аргумент от начала до самого правого /
и cd в него.
[1] Я потратил неприлично много времени, пытаясь сделать это без условного обозначения, связывая вместе имя каталога и ссылку для чтения или просто всегда добавляя ./
перед путем или другими хаками, но у меня всегда была проблема. - либо это будет cd слишком далеко назад (в случае readlink), либо это не будет работать с cding на ..
, или это не будет работать с именами файлов или... да. Если кто-то может сделать это без условного, я очень открыт для предложений.
alias
не считает $@
,$_
(или$anything
)особыми, поэтому они просто дословно передаются оболочке.
Таким образом, ваш оригинал:
alias mvaf="mv $@ && cd $_"
означает, что:
mvaf f dst/
превращается в:
mv $@ && cd $_ f dat/
Поскольку $@
и $_
вряд ли будут определены, оболочка интерпретирует это как:
mv && cd f dat/
, поэтому mv
вызывается без аргумента и выдает ошибку «Отсутствует файловый операнд».
При переопределении как:
alias mvaf="mv $@ "
и выполнить:
mvaf f dst/
превращается в:
mv $@ f dst/
, что, как и прежде, сводится к:
mv f dst/
и заставляет вас думать, что это сработало!