Как мне скопировать с помощью scp с подстановочным знаком (*) в пути назначения?

#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.
  

Чтобы использовать эти функции, поместите курсор до или после * и нажмите либо Controlx * либо Alt*:

 $ pwd
/tmp/expand-glob
$ ls
FILE
$ cp /tmp/expand-*/*
  

Теперь поместите курсор после последнего * , не нажимайте Enter
но Cx * и вы получите это

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