Использование расширения скобок для перемещения файлов в командной строке - PullRequest
2 голосов
/ 25 апреля 2019

У меня есть вопрос, почему это не работает. Возможно, это простой ответ, но я просто не могу понять это.

Я хочу переместить пару файлов, которые у меня есть. Все они имеют одинаковое имя файла (скажем, file1), но все они находятся в разных каталогах (скажем, / tmp / dir1, dir2 и dir3). Если бы я переместил их по отдельности, я мог бы сделать что-то вроде:

mv /tmp/dir1/file1 /tmp

Это работает. Тем не менее, у меня есть несколько каталогов, и все они окажутся в одном месте ... И я не хочу перезаписывать. Итак, я попробовал что-то вроде этого:

mv /tmp/{dir1,dir2,dir3}/file1 /tmp/file1.{a,b,c}

Когда я пытаюсь это сделать, я получаю:

/ tmp / file1.c не является каталогом

Просто чтобы уточнить ... это также работает:

mv /tmp/dir1/file1 /tmp/file1.c

Уверен, это связано с расширением фигурных скобок, но не уверен, почему.

Спасибо

Ответы [ 3 ]

2 голосов
/ 25 апреля 2019

Просто сделайте echo, чтобы понять, как расширяется оболочка:

$ echo mv /tmp/{dir1,dir2,dir3}/file1 /tmp/file1.{a,b,c}
mv /tmp/dir1/file1 /tmp/dir2/file1 /tmp/dir3/file1 /tmp/file1.a /tmp/file1.b /tmp/file1.c

Теперь вы можете видеть, что ваша команда не та, которую вы хотите, потому что в команде mv пункт назначения (каталог или файл) является последним аргументом.

0 голосов
/ 25 апреля 2019

Возможно, вместо a / b / c вы могли бы дифференцировать их по фактическому номеру dir, из которого они вышли?

Соответствующий пункт - расширение скобки не является подстановочным знаком .Это не имеет ничего общего с тем, что на диске.Он просто создает строки.

Итак, если вы создаете группу файлов с именами, состоящими из одной буквы или цифры, echo ? будет подстановочный знак и перечислит их все, но только те, которые на самом деле присутствуют.Если есть файлы для гласных, но не согласных, будут отображаться только гласные.Но -

, если вы скажете echo {foo,bar,nope}, он выдаст foo bar nope независимо от того, существуют ли какие-либо или все из них в виде файлов или каталогов и т. Д.

0 голосов
/ 25 апреля 2019

К сожалению, теперь это работает как расширение оболочки.

Возможно, вам придется использовать ассоциативный массив.

!/bin/bash

declare -A MAP=( [dir1]=a [dir2]=b [dir3]=c )

for ext in "${!MAP[@]}"; do
    echo mv "/tmp/$ext/file1" "/tmp/file1.${MAP[$ext]}"
done

При его запуске вы получите следующий вывод:

mv /tmp/dir2/file1 /tmp/file1.b
mv /tmp/dir3/file1 /tmp/file1.c
mv /tmp/dir1/file1 /tmp/file1.a

Как и во многих других языках, порядок ключей не гарантируется.

${!MAP[@]} возвращает массив всех ключей, а ${MAP[@]} возвращает массив всех значений.


Ваш синтаксис /tmp/{dir1,dir2,dir3}/file1 расширяется до /tmp/dir1/file /tmp/dir2/file /tmp/dir3/file.Это похоже на то, как работает расширение *.Оболочка не выполняет вашу команду с каждой возможной комбинацией, она просто выполняет команду, но расширяет ваше одно значение до необходимого.

...