Изменение каталога путем изменения одного раннего слова в имени пути

{1,2,3}— эторасширение фигурной скобки ,он распространяется на перечисленные слова независимо от их значения.

[...]— это группа символов, используемая врасширении имени файла(или подстановочном знаке или подстановочном знаке )аналогично звездочке *и вопросительному знаку ?. Он соответствует любому отдельному символу, указанному внутри, или символам, которые являются членами именованных групп, таких как [:digit:], если они перечислены. По умолчанию большинство оболочек оставляют подстановочный знак как -, если нет файлов, соответствующих ему.

(Обратите внимание, что вы не можете превратить подстановочный знак/шаблон в набор строк, которым он будет соответствовать. Звездочка может соответствовать любой строке любой длины, поэтому расширение любого шаблона, содержащего ее, приведет к бесконечному списку строк.)

Так:

$ bash -c 'echo [[:digit:]]'           # bash leaves it as-is
[[:digit:]]
$ zsh -c 'echo [[:digit:]]'            # zsh by default complains if no match
zsh:1: no matches found: [[:digit:]]
$ touch 1 3 d i g t
$ bash -c 'echo [[:digit:]]'           # now there are two matches
1 3                                    # note that d, i, g and t do NOT match

Но все же:

$ bash -c 'echo {1,2,3}'
1 2 3

Обе они расширяются оболочкой , не имеет значения, какую команду вы выполняете: ls, echoили rm. Также обратите внимание, что если любой из них указан в кавычках, они не будут расширены:

$ bash -c 'echo "[[:digit:]]"'         # even though matching files still exist
[[:digit:]]
$ bash -c 'echo "{1,2,3}"'
{1,2,3}

10
19.12.2020, 04:20
5 ответов

В некоторых оболочках, напр. kshи zsh, выполнение cd word1 word2приведет к изменению каталога, указанного путем изменения первого вхождения word1в пути к текущему каталогу на word2.

Например, в оболочке zsh:

$ pwd
/usr/local/sbin
$ cd sbin bin
/usr/local/bin
$

В других оболочках, поддерживающих нестандартную -подстановку параметров ${variable/pattern/replacement}, первоначально найденную в ksh93, вы можете использовать ${PWD/word1/word2}для создания пути к каталогу, который будет изменен на:

$ pwd
/usr/local/sbin
$ cd "${PWD/sbin/bin}"
$ pwd
/usr/local/bin

В этих оболочках (bash, например ), можно даже создать свою собственную наивную cdфункцию для обработки двух аргументов так, как это делают kshи zsh, вот так:

cd () {
    if [ "$#" -eq 2 ] && [[ $1 != -* ]]; then
        command cd -- "${PWD/$1/$2}" &&
        printf 'New wd: %s\n' "$PWD"
    else
        command cd "$@"
    fi
}

[ "$#" -eq 2 ]определяет, когда должно запускаться специальное cdповедение (, когда имеется ровно два аргумента командной строки ), но мы проверяем с [[ $1 != -* ]]на , а не запускаем особое поведение, если вы используете опцию с cd. Использование command cdвместо cdвнутри функции позволяет избежать рекурсивного вызова функции.

Проверяем, что вbash:

$ cd /usr/local/sbin
$ cd sbin bin
New wd: /usr/local/bin
$ cd local ''
New wd: /usr/bin
$ cd bin sbin
New wd: /usr/sbin
$ cd sbin local/sbin
New wd: /usr/local/sbin
$ cd '*/' /
New wd: /sbin

Обратите внимание, что последняя команда заменяется шаблоном, соответствующим последнему /; шаблон должен быть указан.Чтобы запретить шаблоны и всегда обрабатывать первый аргумент как слово, используйте command cd "${PWD/"$1"/$2}"в функции (обратите внимание на кавычки$1).

Чтобы дополнительно принудительно заменить только полное имя каталога, используйте command cd "${PWD/"/$1/"/"/$2/"}". Искусственная вставка /до и после обоих аргументов позволит избежать совпадения подстрок имен каталогов, но сделает это несовместимым с тем, как это работает в zshи ksh, и больше не позволит вам делать замены в последней части. пути к каталогу, так как в конце (нет /, вы можете обеспечить только определенный уровень удержания руки -до того, как дополнительная «помощь» станет помехой ).

Это заставит cd foo barработать с примером, который находится в вопросе. В противном случае вам пришлось бы следить за тем, чтобы fooв foobarне совпадало каким-либо другим образом, например, с cd foo/ bar/.

16
18.03.2021, 22:42

Это просто.

cd "$( echo "$PWD" | sed -e 's%/foo/%/bar/%' )"

sedиспользует символ после команды sв качестве разделителя.

2
18.03.2021, 22:42

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

$ pwd
/home/chris/tmp
$ ln -s /home/mythtv/video/tv/tmp 
$ cd tmp
$ ls
$ cd../ 
$ mv 852f.mkv tmp
$ ls tmp
852f.mkv
$ rm -i tmp
rm: remove symbolic link 'tmp'? y
$ ls /home/mythtv/video/tv/tmp
852f.mkv
0
18.03.2021, 22:42

Иногда проще использовать мышь , если вы используете хороший эмулятор терминала на графическом рабочем столе. Или в screenили современном эквиваленте вы можете использовать элементы управления с клавиатуры для копирования/вставки текста.

$ pwd
/some/long/path

скопируйте/вставьте этот путь в команду cd(, т. е. дважды -щелкните по нему, чтобы выбрать все, или трижды, чтобы получить всю строку, если есть пробелы. Если да, то введите одну кавычку -перед вставкой ).

Затем используйте клавиши редактирования строки -вашей оболочки, чтобы отредактировать ее ранний компонент, например. в режиме Bash emacs,

  • ctrl -a для перемещения курсора в начало строки
  • ctrl -вправо -стрелка (или alt -f )пару раз, чтобы пройти вперед по словам до нужного компонента.
  • alt -d или alt -backspace, чтобы удалить целое слово вперед или назад.
  • введите замену (с завершением табуляции )и нажмите клавишу возврата

Если вы что-то нащупываете, это всего лишь cdкоманда, так что ничего деструктивного она не сделает.

0
18.03.2021, 22:42

В cli вы можете использовать модификатор, как в этом примере:

$ mkdir -p foobar/foo/data/images/2020/01/14/0001/
mkdir: created directory 'foobar'
mkdir: created directory 'foobar/foo'
mkdir: created directory 'foobar/foo/data'
mkdir: created directory 'foobar/foo/data/images'
mkdir: created directory 'foobar/foo/data/images/2020'
mkdir: created directory 'foobar/foo/data/images/2020/01'
mkdir: created directory 'foobar/foo/data/images/2020/01/14'
mkdir: created directory 'foobar/foo/data/images/2020/01/14/0001/'
$ ^bar/foo^bar/bar^
mkdir -p foobar/bar/data/images/2020/01/14/0001/
mkdir: created directory 'foobar/bar'
mkdir: created directory 'foobar/bar/data'
mkdir: created directory 'foobar/bar/data/images'
mkdir: created directory 'foobar/bar/data/images/2020'
mkdir: created directory 'foobar/bar/data/images/2020/01'
mkdir: created directory 'foobar/bar/data/images/2020/01/14'
mkdir: created directory 'foobar/bar/data/images/2020/01/14/0001/'

Пояснение:

Первая команда создает вложенные каталоги, начинающиеся с foobar. Вторая команда использует модификатор ^ для замены строки в предыдущей команде новой строкой. Легко сделать ошибку, набрав следующее:

^foo^bar^

Однако это изменит команду на

mkdir -p barbar/foo/data/images/2020/01/14/0001/

, потому что это также повлияет на ведущий foo. Чтобы избежать этого, вы можете использовать некоторые символы до или после предполагаемой строки.

В этом примере я использовал mkdir, но cd аналогичен. ХТН.

2
18.03.2021, 22:42

Теги

Похожие вопросы