Как записать выражение с помощью терминала bash?

Друг помог мне разобраться -Я находился в каталоге, содержащем мои учетные данные, во время выполнения команды, но мне нужно было указать абсолютный путь. Я не уверен, связано ли это с тем, что мой домашний каталог находится в /mnt, но в любом случае следующий подход работает успешно:

$ sudo mount -t cifs -o credentials=/mnt/path/to/mycreds //mydomain/share/Users/me /mnt/mydir
# Success
0
12.03.2020, 09:11
2 ответа

Лучше всего использовать пакетный инструмент для переименования файлов, такой как zshzmv, mmvили один из вариантовrename:

на основе Perl -.
zsh << 'EOF'
autoload zmv
zmv 'log_(*).txt' '${1}_log.txt'
EOF

Или

prename 's/log_(.*)\.txt/${1}_log.txt/' log*.txt
1
28.04.2021, 23:20

Допустим, у вас есть имя одного из этих файлов в переменной оболочки name. Затем удаление бита log_из значения переменной выполняется с помощью ${name#log_}, а удаление бита .txtвыполняется с помощью ${name%.txt}. Остается дата, а в каком она формате - по сути не интересно. Было бы легко взять удаленное значение и добавить в его конец _log_.txt, чтобы создать новое имя.

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

shopt -s nullglob

for name in root/log_*.txt; do
    newname=root/${name#root/log_}    # remove prefix, add root/ back
    newname=${newname%.txt}_log.txt   # remove suffix, add _log.txt back

    printf 'Would move "%s" to "%s"\n' "$name" "$newname"
    # mv -i "$name" "$newname"
done

Я закомментировал реальную команду mvдля безопасности. Вы должны запустить -один раз, чтобы увидеть, что произойдет в первую очередь.

Параметр оболочки nullglobзаставляет оболочку bashудалять несопоставленные шаблоны, а не оставлять их нераскрытыми. Это означает, что цикл вообще не запустился бы, если бы в данном каталоге не было файлов log_*.txt.

Это можно применить к любому такому файлу в текущем каталоге (, включая текущий каталог )рекурсивно, более или менее просто изменив шаблон, который мы повторяем:

shopt -s globstar nullglob

for name in./**/log_*.txt; do
    dirpath=${name%/*}                      # get path of directory
    newname=$dirpath/${name#$dirpath/log_}  # remove prefix, add directory path back
    newname=${newname%.txt}_log.txt         # remove suffix, add _log.txt back

    printf 'Would move "%s" to "%s"\n' "$name" "$newname"
    # mv -i "$name" "$newname"
done

Другие изменения включают в себя включение опции оболочки globstar, которая позволяет нам использовать **для сопоставления с подкаталогами. Кроме того, я выбираю путь к каталогу, чтобы добавить его к новому имени.

Вы также можете использовать findдля создания входных данных для цикла:

find. -type f -name 'log_*.txt' -exec sh -c '
    for name do
        dirpath=${name%/*}                      # get path of directory
        newname=$dirpath/${name#$dirpath/log_}  # remove prefix, add directory path back
        newname=${newname%.txt}_log.txt         # remove suffix, add _log.txt back

        printf "Would move \"%s\" to \"%s\"\n" "$name" "$newname"
        # mv -i "$name" "$newname"
    done' sh {} +

Это позволит найти все обычные файлы, чьи имена совпадают с log_*.txtв текущем каталоге или ниже, а затем передать их пакетами сценарию в -строке sh -c, который, по сути, будет выполнять ту же работу, что и цикл. во втором варианте выше.

3
28.04.2021, 23:20

Теги

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