Как переименовать определенные каталоги, если родитель имеет определенное имя?

Вы можете запустить C64 в браузере и использовать BASIC таким образом.

http://codeazur.com.br/stuff/fc64_final/

Учтите, что раскладка клавиатуры отличается, т.е. Shift-2 для кавычек.

http://jilltxt.net/wp-content/uploads/C64-keyboard-layout.png

Applesoft BASIC, если вы предпочитаете - http://calormen.com/jsbasic/

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

1
05.05.2016, 02:07
2 ответа

1

Для вашего первого шага в вашем примере команды вам не нужен * , потому что он не фильтрует ни один файл. Что вам действительно нужно, так это отфильтровать .git , как это:

$ find . -name '.git' -prune -o -type f -print

Это отклонит ( -prune ) любой каталог с точным именем .git и все, что внутри Это.

Это устраняет необходимость grep -v ".git" . Нельзя было избежать sed, поскольку он редактирует внутреннюю часть файла, а не то, что может сделать find.

Но все же мы можем упростить (цитируя точку внутри sed):

$ find . -name '.git' -prune -o -type f -exec sed -i 's/com\.foo/org\.bar/g' '{}' \+

Это накапливает имена файлов (аналогично xargs) в команде sed .

Но даже лучше:

$ find . -name '.git' -prune -o -type f -execdir sed -i 's/com\.foo/org\.bar/g' '{}' \+

Которая будет выполнять по одному экземпляру sed для каждого каталога.

2 и 3

Давайте определим функцию для выполнения переименования каталога:

$ renamedir (){ find "$1" -name '.git' -prune -o -type d -exec bash -c 'mv "$1" "${1//"$2"/$3}"' sh '{}' "$2" "$3" \; ; }

Шаг 2:

  • для всех каталогов (кроме .git) в src / com переименовать в src / org

     $ renamedir 'd / src / com' src / com 'src / org' 
     

Шаг 3:

  • для всех каталогов (кроме .git) в src / org / foo переименовать в src / org / bar

     $ renamedir 'src / org / foo' 'ogr / foo' 'org / bar' 
     

4

Шаг 4:

  • для всех имен файлов и каталогов ( исключая .git) с com.foo в имени, измените эту часть на org.bar.

     $ find. -name '.git' -prune -o -name "com.foo" -type f -exec bash -c 'mv "$ 1" "$ {1 //" $ 2 "/ $ 3}"' sh '{}' " com.foo "" org.bar "\; ; } 
     

Все внутри (лучше отформатированного) сценария:

#!/bin/bash

# NOTE: There are three echo to avoid execution of commands.
#       If after testing, you decide that it is ok to execute commands,
#       remove the echo words.

# Step 1:
### for all files (excluding .git) in . change
###     file contents from com.foo to org.bar
find . -name '.git' -prune -o -type f -execdir echo sed -i 's/com\.foo/org\.bar/g' '{}' \+

renamedir (){ find "$1" -name '.git' -prune -o -type d -exec bash -c '
                  echo \
                  mv "$1" "${1//"$2"/$3}"
              ' sh '{}' "$2" "$3" \;
        }

# Step 2:
### for all directories (excluding .git) in src/com rename to src/org
renamedir 'd/src/com' 'src/com' 'src/org'

# Step 3:
### for all directories (excluding .git) in src/org/foo rename to src/org/bar
renamedir 'src/org/foo' 'org/foo' 'org/bar'

# Step 4:
### for all file and directory names (excluding .git)
### with "com.foo" in the name, change that portion to "org.bar".
find . -name '.git' -prune -o -name "*com.foo*" -type f -exec bash -c '
    echo \
    mv "$1" "${1//"$2"/$3}"
' sh '{}' "com.foo" "org.bar" \; ; }

Чтобы проверить различные версии сопоставления, создайте целое дерево файлов, как это (удалите его позже с помощью rm -rf./ d / ):

$ mkdir -p d/src/{{,.git}{,one},com/{{,.git}{,two},\ .git,.git/six},org/{{,.git}{,three},bar/{,.git}{,four},foo/{,.git}{,five}}}
$ touch d/src/{111,com/{222,.git/666},org/{333,bar/444,foo/555}}  
$ touch d/src/{.git/{aaa,one/aaaaa},one/aaa111,com/.git{/bbb,two/bbb222},org/{.git{/ccc,three/ccc333},bar/.git{/ddd,four/ddd444},foo/.git{/eee,five/eee555}}}               

Ваша исходная команда (с использованием параметра GNU -z для сопоставления find -print0) будет соответствовать (в этом каталоге):

$ find d/ -type f -print0 | grep -zZv \.git
find d/ -type f -print0 | grep -zZv \.git | xargs -0 printf '<%s>\n'
<d/src/org/333>
<d/src/org/foo/555>
<d/src/org/bar/444>
<d/src/com/222>
<d/src/111>

Только пять файлов, которые не имеют отношения ни к чему .git .


В общем:

Есть три основных способа сопоставить .git в find : -name , -regex и -path . Оставляя в стороне -regex , который помимо нечетного (использует регулярное выражение emacs), необходим только для сложных совпадений, которые здесь не нужны.

find d / -path "./.git" будет соответствовать именно этому: только внутреннему каталогу .git .
Или (для созданного каталога) найти. -path './d/src/.git' будет соответствовать только ./ d / src / .git

A find d / -name ".git" будет соответствовать ровно .git на последнем уровне (базовом имени) дерева.

И -name "* .git" , и -path "* .git" будут совпадать.
Любая строка, которая заканчивается на .git .

Что начинает усложняться, так это когда мы добавляем две звездочки: *. Git *
В этом случае -name будет соответствовать только на последнем уровне пути (базовое имя файла), но из-за наличия двух звездочек * также будет соответствовать именам с префиксом (обратите внимание на пробел в .git ) и постфиксом (обратите внимание на многие, такие как .gitone ):

$ find d -name '*.git*'
d/src/org/.gitthree
d/src/org/foo/.git
d/src/org/foo/.gitfive
d/src/org/bar/.gitfour
d/src/org/bar/.git
d/src/org/.git
d/src/com/.gittwo
d/src/com/.git
d/src/com/ .git
d/src/.git
d/src/.gitone

будет соответствовать .git на любом уровне пути, почти как grep.Не совсем то же самое, что grep, поскольку grep может иметь сложное Regex, но здесь совпадение противоречит простому «шаблону». Обратите внимание на d / src / com / .git / six ниже:

$ find d -path '*.git*'
d/src/org/.gitthree
d/src/org/foo/.git
d/src/org/foo/.gitfive
d/src/org/bar/.gitfour
d/src/org/bar/.git
d/src/org/.git
d/src/com/.gittwo
d/src/com/.git
d/src/com/.git/six
d/src/com/ .git
d/src/.git
d/src/.gitone

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

Не (!)

Если найти d -name '.git' будет соответствовать:

d/src/org/foo/.git
d/src/org/bar/.git
d/src/org/.git
d/src/com/.git
d/src/.git

Тогда найти d -not -name '.git' (или, точный эквивалент: find d! -name '.git' ) будет соответствовать всем остальным. Здесь не печатается, поскольку список довольно долго.

Но выбор только файлов короткий (обратите внимание на файл 666 ):

$ find d -not -name '.git' -type f
d/src/org/333
d/src/org/foo/555
d/src/org/bar/444
d/src/com/222
d/src/com/.git/666
d/src/111

И -path в find d -not -path '* .git *' -type f будет соответствовать только пяти файлам:

$ find d -not -path '*.git*' -type f
d/src/org/333
d/src/org/foo/555
d/src/org/bar/444
d/src/com/222
d/src/111

Prune

Или мы можем использовать -prune , чтобы «вырезать» или «удалить» все каталоги, которые соответствуют предыдущему принято:

$ find d \( -name '.git' -prune \) -o \( -print \)
d
d/src
d/src/org
d/src/org/three
d/src/org/333
d/src/org/.gitthree
d/src/org/foo
d/src/org/foo/five
d/src/org/foo/555
d/src/org/foo/.gitfive
d/src/org/bar
d/src/org/bar/.gitfour
d/src/org/bar/four
d/src/org/bar/444
d/src/one
d/src/com
d/src/com/.gittwo
d/src/com/222
d/src/com/two
d/src/com/ .git
d/src/111
d/src/.gitone

Должно быть что-то после -prune. Обычно "-o", а здесь также -print , чтобы соответствовать всему, что обрезка не соответствует. Как видите, это совпадение намного больше, чем пять файлов вашей команды. Замена '. Git' на '*. Git' удалит только ] d / src / com / .git . Но использование '*. git *' будет работать ближе к grep (все еще не совсем то же самое):

$ find d \( -name '*.git*' -prune \) -o \( -print \)
d
d/src
d/src/org
d/src/org/three
d/src/org/333
d/src/org/foo
d/src/org/foo/five
d/src/org/foo/555
d/src/org/bar
d/src/org/bar/four
d/src/org/bar/444
d/src/one
d/src/com
d/src/com/222
d/src/com/two
d/src/111

Это будет соответствовать только пяти файлам (не каталогам) вашей команды:

$ find d \( -name '*.git*' -prune \) -o \( -type f -print \)

Также это будет соответствовать только первым пяти файлам.Добавление -типа f скрывает множество деталей:

$  find d \( -name '.git' -prune \) -o \( -type f -print \)

Обычно без скобок (менее ясно):

$ find d -name '.git' -prune -o -type f -print

Предупреждение: удаление -print может иметь непредвиденные побочные эффекты.

1
27.01.2020, 23:48

Замена в файлах

Ваша команда ненадежна по нескольким причинам : она исключает все пути, содержащие .git в качестве подстроки, она не работает с путями, содержащими пробелы или \ '", он заменяет ввод любым символом между com и foo . Последняя проблема легко решается добавлением обратной косой черты перед точкой. имена файлов могут быть, а могут и не быть проблемой в вашей настройке - деревья исходных текстов имеют тенденцию быть ручными. Также -name "*" является избыточным (оно всегда совпадает). Вот безопасная и более простая альтернатива, которая должным образом опускает поддерево .git .

find . -name .git -prune -o -type f -exec sed -i 's/com\.foo/org.bar/g' {} +

Это все еще заменяет, например, com.fooalso на org.baralso , что, вероятно, нежелательно, если это произойдет. Вот более безопасная конструкция ction:

find . -name .git -prune -o -type f -exec sed -i -e 's/com\.foo$/org.bar/' -e 's/com\.foo\([^-_0-9A-Za-z]\)/org.bar\1/' {} +

Переименование файлов с помощью zsh

Загрузите функцию zmv с автозагрузкой -U zmv , затем вы можете использовать ее для переименования файлов на основе шаблонов подстановочных знаков . Я думаю, что вы ищете на самом деле

zmv -w '**/com/foo' '$1/org/bar'
zmv -w '**/*com.foo' '$1/${2}org.bar'
zmv '(**/)(*)com.foo([^-_0-9A-Za-z]*)' '$1${2}org.bar$3'
0
27.01.2020, 23:48

Теги

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