#bash #shell #copy #wildcard
#bash #оболочка #Копировать #подстановочный знак
Вопрос:
Возможно ли получить значение, которому соответствует подстановочный знак? Т.е. я хочу сделать
scp -r user@host:some/path/with/*/file.txt cp/to/*/file.txt
С помощью приведенной выше команды я хочу
some/path/with/TEST/file.txt --> cp/to/TEST/file.txt
some/path/with/OTHER/file.txt --> cp/to/OTHER/file.txt
Редактировать:
Я добавлю еще некоторые данные моей фактической настройки, которые могут сделать ее более понятной.
На моем сервере у меня есть структура
server $ pwd
~/sixtrack/simulations
server $ ls
run0001
run0002
run0003
...
Каждый run*
из них представляет собой каталог, содержащий такие файлы, как run*/summary.dat
, run*/tracks.dat
и т.д. Я мог бы скопировать все на свой компьютер, например
pingul $ scp -r 'user@host:sixtrack/simulations/*' .
Однако я бы хотел копировать не каждый файл, а только некоторые. Поскольку все файлы имеют одинаковые имена и разделяются только по каталогу, я должен соблюдать структуру. Таким образом, я хотел host:sixtrack/simulations/run0001/summary.dat
бы перейти в свою локальную папку /Users/pingul/Workspace/simulations/run0001/summary.dat
.
Выполняется
pingul $ pwd
/Users/pingul/Workspace/simulations
pingul $ scp -r 'user@host:sixtrack/simulations/*/summary.dat' */.
Не выполняет то, что я хочу. Добавление -v
предложенной опции выводит
Executing: cp -r -- run0001/. run0100/.
Executing: cp -r -- run0002/. run0100/.
Executing: cp -r -- run0003/. run0100/.
...
и я получаю только один summary.dat
run0100
. Все остальные каталоги пусты (т.Е. run0001
, run0002
, …)
Возможно ли то, что я хочу?
Комментарии:
1. У вас есть папка с именем cp …?
2. @123 Нет, он просто предназначен для чтения. Например, «копировать в …».
3.
cp
вverbose
режиме, т.е.-v
флаг может печатать полный путь к каталогу назначения.4. @Inian Не могли бы вы уточнить, как я буду использовать его для достижения того, чего я хочу?
5. @pingul: добавьте флаг
-v
в свой scp, чтобы увидеть то, что я упоминал ранее. У меня есть проблема, вы просто хотите узнать пути назначения, расширенные с помощью подстановочного знака, или выполнить какую-либо операцию?
Ответ №1:
Это зависит от того, хотите ли вы развернуть *
перед выполнением команды или после ее выполнения, и хотите ли вы сделать это интерактивно или нет.
Если вы хотите развернуть его перед интерактивным запуском команды, вы можете использовать insert-completions (M-*)
или glob-expand-word (C-x *)
описать в man bash
:
glob-expand-word (C-x *)
The word before point is treated as a pattern for
pathname expansion, and the list of matching filenames
is inserted, replacing the word. If a numeric argument
is sup- plied, an asterisk is appended before pathname
expansion.
insert-completions (M-*)
Insert all completions of the text before point that
would have been generated by possible-completions.
Чтобы использовать эти функции, поместите курсор до или после *
и нажмите либо Control—x * либо Alt—*:
$ pwd
/tmp/expand-glob
$ ls
FILE
$ cp /tmp/expand-*/*
Теперь поместите курсор после последнего *
, не нажимайте Enter
но C—x * и вы получите это
$ cp /tmp/expand-glob/FILE
Если вы хотите развернуть *
команду test в скрипте
scp
, то ни cp
один из них не является хорошим вариантом, потому что не может выполняться в dry-run
режиме. Вы должны пойти с чем-то подобным rsync
, чтобы показать, какие
файлы он будет передавать, если он действительно был запущен таким образом:
$ rsync -vn --relative /tmp/expand-*/* .
/tmp/
/tmp/expand-scp/
/tmp/expand-scp/a
/tmp/expand-scp/b
/tmp/expand-scp/c
/tmp/expand-scp/mmmm32
Редактировать:
Как насчет этого:
$ rsync -avn -R --rsync-path="cd sixtrack/simulations amp;amp; rsync" user@host:run*/summary.dat .
-n
означает пробный запуск. С помощью этой опции rsync
будет выводиться только то, как будет воссоздана структура удаленных каталогов в текущем каталоге. В вашем случае это будет что-то вроде:
receiving incremental file list
drwxr-xr-x 4,096 2016/10/13 12:45:36 run0001
-rw-r--r-- 0 2016/10/13 12:23:18 run0001/summary.dat
drwxr-xr-x 4,096 2016/10/13 12:23:18 run00010
-rw-r--r-- 0 2016/10/13 12:23:18 run00010/summary.dat
drwxr-xr-x 4,096 2016/10/13 12:23:18 run0002
-rw-r--r-- 0 2016/10/13 12:23:18 run0002/summary.dat
drwxr-xr-x 4,096 2016/10/13 12:23:18 run0003
-rw-r--r-- 0 2016/10/13 12:23:18 run0003/summary.dat
drwxr-xr-x 4,096 2016/10/13 12:23:18 run0004
-rw-r--r-- 0 2016/10/13 12:23:18 run0004/summary.dat
drwxr-xr-x 4,096 2016/10/13 12:23:18 run0005
-rw-r--r-- 0 2016/10/13 12:23:18 run0005/summary.dat
drwxr-xr-x 4,096 2016/10/13 12:23:18 run0006
-rw-r--r-- 0 2016/10/13 12:23:18 run0006/summary.dat
drwxr-xr-x 4,096 2016/10/13 12:23:18 run0007
-rw-r--r-- 0 2016/10/13 12:23:18 run0007/summary.dat
drwxr-xr-x 4,096 2016/10/13 12:23:18 run0008
-rw-r--r-- 0 2016/10/13 12:23:18 run0008/summary.dat
drwxr-xr-x 4,096 2016/10/13 12:23:18 run0009
-rw-r--r-- 0 2016/10/13 12:23:18 run0009/summary.dat
Комментарии:
1. Спасибо за ваш ответ. Я не уверен, насколько это применимо к моей ситуации, но, возможно, я был неясен в своем вопросе. Я добавил более конкретную информацию в сообщение. Не могли бы вы объяснить, как я буду использовать ваш случай в своем сценарии?
2. Это работает как шарм! Не могли бы вы изменить свой ответ, чтобы он также включал последний вызов? (т. Е. Мне нужно добавить ` . ` к вашей строке выше, чтобы она действительно выполняла копирование)
3. @pingul: Я рад, что это работает для вас! Я добавил недостающую точку.
Ответ №2:
То, о чем вы просите, невозможно, поскольку cp
/ scp
команды принимают только одно назначение. Однако вы можете легко смоделировать это с помощью некоторых очень простых сценариев:
for d in *
do
scp -r user@host:some/path/with/"$d"/file.txt cp/to/"$d"/file.txt
done
Он также может быть записан в одной строке как
for d in *; do scp -r user@host:some/path/with/"$d"/file.txt cp/to/"$d"/file.txt; done
Комментарии:
1. Я пробовал это раньше, однако каждый вызов генерирует запрос пароля, что делает метод неосуществимым.