
function mv1 { mv -n "$1" "targetdir" -v |wc -l ;}
mv1 *.png
Он перемещает только первый .png
найденный файл, а не все.
Как сделать так, чтобы команда применялась ко всем файлам, соответствующим подстановочным знакам?
решение1
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 ;}
This is almost correct, but it still fails if a file name happens to begin with the character -
, because mv
will treat that argument as an option. Pass --
to mv
to tell it “no more options after this point”. This is a very common convention that most commands support.
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]}}))
}
решение2
$1
— это первый аргумент функции, здесь первый файл, который соответствует *.png
. Я думаю, это "$@"
то, что вы хотите использовать вместо $1
.
решение3
Вам придется использовать mv1 \*.png
.
При взаимодействии с функциями Linux Terminal не передает звездочку напрямую команде, а выбирает первый соответствующий параметр и передает его команде.
Чтобы разрешить прямую передачу звездочки, ее необходимо экранировать с помощью обратной косой черты.