Как найти/заменить символы в имени папки?

Да, командная строка будет различаться в зависимости от того, какой именно системный вызов exec * был выполнен, и полностью квалифицированный путь может отличаться от того, который env (1) обнаруживает при поиске пути.

bash-4.1$ cat aaa
#!/bin/bash
xxd /proc/$$/cmdline
bash-4.1$ cat bbb
#!/usr/bin/env bash
xxd /proc/$$/cmdline
bash-4.1$ ./aaa
0000000: 2f62 696e 2f62 6173 6800 2e2f 6161 6100  /bin/bash../aaa.
bash-4.1$ ./bbb
0000000: 6261 7368 002e 2f62 6262 00              bash../bbb.
bash-4.1$ 

strace показывает подробности:

bash-4.1$ strace ./aaa 2>&1 | grep exec
execve("./aaa", ["./aaa"], [/* 57 vars */]) = 0
bash-4.1$ strace ./bbb 2>&1 | grep exec
execve("./bbb", ["./bbb"], [/* 57 vars */]) = 0
execve("/sbin/bash", ["bash", "./bbb"], [/* 57 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/sbin/bash", ["bash", "./bbb"], [/* 57 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/local/sbin/bash", ["bash", "./bbb"], [/* 57 vars */]) = -1 ENOENT (No such file or directory)
execve("/bin/bash", ["bash", "./bbb"], [/* 57 vars */]) = 0
bash-4.1$ 

Если это сценарий только для Linux, то местоположение bash , скорее всего, не будет изменяться (исключение: есть хранилище программного обеспечения, которое включает bash , в другом месте). Следовательно, использование полного пути, вероятно, имеет наибольший смысл, поскольку это позволяет избежать ошибок env (1) при поиске пути и обеспечивает совместимость с инструментами инициализации.

1
15.09.2018, 22:28
2 ответа

Первые два примера являются выходом из положения.

  • *<>:\|?*Вы не можете начать с *. *означает 0 или более предыдущих атомов. Он также говорит <, за которым следует >, за которым следует :…, а ?— это специальный символ.
  • *[<>:\|?]*Это ближе к тому, что вы используете класс символов, но все же *в начале.
  • [<>:\|?]Это совпало бы, если бы это было совпадение под-регулярного выражения, но это не так. Вам нужно сопоставить полное имя файла, включая путь к каталогу.

Поэтому добавьте коды регулярных выражений, чтобы потреблять данные до и после.(.— любой символ, *— ноль или более гарантий предыдущего атома. Поэтому .*будет соответствовать чему угодно.)

Поэтому попробуйте.*[<>:\|?].*

Вы не собираетесь заменять ничего подобного, и вы не сказали нам, на что вы хотите их заменить.

4
27.01.2020, 23:12

Используйте -nameвместо -regex(, так как это имена файлов, которые вас действительно интересуют, и -regexсоответствует всему пути):

find folder -type d -name '*[<>:\|?]*'

Будет найден любой каталог внутри или ниже folder, имя которого содержит хотя бы один из символов <, >, :, \, |или ?.

Чтобы удалить эти символы из имен каталогов:

find folder -depth -type d -name '*[<>:\|?]*' \
    -execdir bash -c 'mv "$1" "${1//[<>:\|?]/}"' bash {} ';'

Это предполагает, что новое имя переименованного каталога еще не является именем существующего каталога. Добавление теста на конфликты имен:

find folder -depth -type d -name '*[<>:\|?]*' \
    -execdir bash -c '[ ! -e "${1//[<>:\|?]/}" ] && mv "$1" "${1//[<>:\|?]/}"' bash {} ';'

Это позволит избежать попыток переименовать каталог, если новое имя уже существует

Команда mvвыполняется в дочерней оболочке bash. Оболочка выполняется с родительским каталогом найденного каталога в качестве рабочего каталога. Он использует подстановку специального параметраbash-для удаления всех оскорбительных символов из имен файлов найденных каталогов.

Команда также использует -depthдля глубокого -первого обхода структуры каталогов в folder. Без этого findпопытается войти в каталоги, которые вы только что переименовали, и потерпит неудачу.

Связанные:

3
27.01.2020, 23:12

Теги

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