Я пока не знаю, в чем проблема, но у меня есть несколько замечаний о вашем сценарии.
Старайтесь не вызывать двоичные файлы (с одним фрагментом данных) в цикле. Это убивает производительность.
Вы должны вызвать весь сценарий с sudo, но не sudo в скрипте.
Для изменения имен файлов не требуется sed
. bash
может сделать это самостоятельно:
if [[ $dir =~ "Season 0" ]]; then
new="${dir/Season 0/Sn}"
else
new="${dir/Season /Sn}"
fi
Или без , если
:
new="${dir/Season /Sn}"
new="${new/Sn0/Sn}"
Массив не нужен:
find ... | while read dirpath; do
Это имеет то «преимущество», что места в имени каталога не нарушают определение массива. Я понятия не имею, почему ваш массив = "$ (найти... -print) "
работает. Он не должен (потому что оболочка не должна иметь разницы в разделении слов между космосом и новой строкой).
Проблема заключается в том, что создается не массив, а последовательность. Вы можете легко проверить это, попытавшись напечатать первый элемент массива:
$ array="$(find . -maxdepth 2 -type d -iname 'Season*' -print)";
$ echo $array
./Season 3 ./Season 1 ./Season 2
Выглядит правильно? Но если бы это был массив, можно было бы напечатать каждый элемент отдельно. К сожалению, вышесказанное является простым рядом 1 , а не массивом:
$ echo ${array[0]}
./Season 3 ./Season 1 ./Season 2
$ echo ${array[1]}
Массив фактически состоит из одного ряда, из-за чего второй элемент «массива» ( $ {array [1]}
) пуст. В любом случае массив для этого не нужен, просто прочитайте выходные данные find
(также не нужен -print
, это то, что он делает по умолчанию). Рабочая версия вашего сценария может быть:
#!/usr/bin/env bash
find . -maxdepth 2 -type d -iname 'Season*' | sort -r |
while IFS= read -r dir
do
mv "$dir" ${dir/Season /Sn} && echo Changed "$dir" to "$dir/Season /Sn}";
done
Там используется пара трюков. Сначала выполните цикл while
для просмотра результатов поиска
. Это тот же самый основной принцип, что и для цикла
, который вы использовали, но в сочетании с read
могут считывать из стандартного ввода.
Во избежание разделения на пробелы IFS =
(без него каталог Season 1
будет разделен на Season
и 1
).
В -r
чтения указано, что нельзя использовать обратную косую черту для обхода символов (такие вещи, как \t
и \n
, обрабатываются буквально), что обеспечивает возможность использования даже самых странных имен.
sort -r
необходим для того, чтобы при наличии каталога, соответствующего образцу, в другом соответствующем каталоге нижестоящий элемент был указан перед родительским. Например,
./Season 12/Season 13
./Season 12
Это обеспечивает запуск mv «Season 12» «Sn12»
после running mv «Season 12 »/« Season 13» «Season 12 »/« Sn13»
. Если этого не сделать, вторая команда завершится ошибкой, поскольку Season 12
больше не существует.
Наконец, я удалил sudo
. Вместо этого следует запустить сценарий sudo script.sh
. Никогда не рекомендуется использовать случайные sudo
вызовы в сценариях.
1 Я не уверен в деталях, но, очевидно, bash рассматривает переменные строки как массивы одного элемента.
Я получил сюда после получения разрешений на мое/домашнее подключение после изменения размера логического тома/root и/home. Я удалил и заново создал/home том и обнаружил, что/home нуждается в 755 разрешениях, чтобы позволить пользователям войти и получить доступ к своим/home/user каталогам.
Я сделал:
chmod 755/home
и это сделал трюк.
Необходимо указать зеркало CRAN; в интерактивном режиме в R выполните
chooseCRANmirror()
, чтобы выбрать соответствующее зеркало, затем
options("repos")
, чтобы увидеть результирующий URL. Вы можете добавить это навсегда в свою конфигурацию в ~/.Rprofile
:
local({r <- getOption("repos")
r["CRAN"] <- "<URL from above goes here>"
options(repos=r)
})
-121--166882- #!/system/bin/sh -xv
Z=/absolute/path/to/WorkingDir
T=320
F=480 # ?
I=540 # ?
D=dark
L=light
P=play # ?
cd $Z
for dir in $Z*/*/; do
if [ -d $Z/$T/$D ] && [ ! -f $T$D.zip ]; then
zip -0rq $T$D.zip $dir;
elif [ -d $Z/$T/$L ] && [ ! -f $T$L.zip ]; then # elif rules
zip -0rq $T$L.zip $dir;
# It's not very efficient to scale this up, but you could add more elif statements here.
elif [ -d $Z/$F/$D ] && [ ! -f $F$D.zip]; then
zip -0rq $F$D.zip $dir;
# and so on..
else
exit
fi;
done
Я думаю, что это все, что вам нужно. Дайте мне знать, если это нуждается в каких-либо корректировках.
Вот мое предложение, удаление однобуквенных переменных и изменение местоположения архива для согласованности:
#!/system/bin/sh -xv
cd "$PWD/../WorkingDir"
compress() {
# Detect only known dir names, convert slash to underscore
local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')"
# Set a default value to the variable
: ${arch:=file}
# Only create a ZIP archive if not present in the parent directory
# Note $PWD is evaluated *before* cd
[ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." )
}
for dir in */*/; do
compress $dir
done
Просто измените строку sed
, чтобы добавить то, что я назвал «хорошо известными именами каталогов».
РЕДАКТИРОВАТЬ : Добавление нескольких пояснений в соответствии с запросом OP.
Сценарий проверяет условия перед архивированием каталогов каждый раз, когда цикл for
находит новый каталог. Переменные также были удалены. Давайте разберем код.
cd "$PWD/../WorkingDir"
for dir in */*/; do # Ensures to select only directories
compress $dir # compress runs some checks prior to compressing
done
На самом деле больше нечего сказать об этом.
сжатия
local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')"
$ 1
- это аргумент, передаваемый в сжатый
, то есть каталог для проверки и сжатия. Сначала sed
( '/ 320 \ / (light | dark) /'
) проверяет, имеет ли путь форму
320/light
320/dark
, и возвращает путь с преобразованной косой чертой. до подчеркивания: 's @ / @ _ @ g'
. Использование знака at в качестве разделителя для удобства чтения, чтобы избежать косой черты. Другие допустимые обозначения: 's: /: _: g'
или 's # / # _ # g'
или классический 's / \ // _ / g '
. Обратите внимание, как косая черта, которую нужно преобразовать, заменяется анти косой чертой. Я считаю, что последняя форма менее читабельна.
Завершающий p
работает вместе с sed -n
; последний вариант в данном конкретном случае означает « ничего не выводить, если не указано в p
всякий раз, когда найдено совпадение (то есть в закрывающих косых чертах) ». Следовательно, arch
будет содержать путь с косой чертой, преобразованной в подчеркивание тогда и только тогда, когда регулярное выражение 320 \ / (light | dark)
находится в дорожка. В противном случае он ничего не отобразит, что сделает arch
пустой переменной.
Опция -r
- удобный способ указать sed
использовать канонические регулярные выражения, более удобочитаемые. В противном случае вам нужно будет экранировать символы круглых скобок и вертикальной черты. Я считаю '/ 320 \ / (светлый | темный) / s @ / @ _ @ gp'
более читабельным, чем '/ 320 \ / \ (светлый \ | темный \) / s @ / @ _ @ gp '
или ' / 320 \ / \ (светлый \ | темный \) / s / \ // _ / gp '
.
: ${arch:=file}
В этой строке arch
устанавливается значение по умолчанию «файл», если оно пустое. Странная конструкция требуется, потому что только $ {arch: = file}
вызывает синтаксическую ошибку. Двоеточие указывает оболочке ничего не делать (:
), а присваивать arch
значение, если оно пустое.
[ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." )
Здесь я использовал -f
вместо -e
, потому что первый также проверяет файлы нулевой длины. Тест будет успешным, только если существует ZIP-архив и имеет ненулевую длину.
Если в родительском (или текущем ) каталоге сценария нет архивного файла или если его размер равен нулю, то сценарий порождает суб-оболочку, которая изменяет каталог, переданный в качестве аргумента сжать
и заархивировать его содержимое. Обратите внимание, что переменные $ 1
и $ PWD
оцениваются до того, как суб-оболочка выполнит свои инструкции, т. Е. $ PWD
эквивалентен родительскому каталогу $ Z
в вашей начальной версии.
Вы можете действовать на sed
следующим образом:
sed -rne '/320\/(light|dark|play)/s@/@_@gp'
для проверки имен каталогов, таких как
320/light
320/dark
320/play
Вы также можете рассмотреть / (320 | 480 | 540 ) \ / (light | dark | play) /
, что дает вам 9 комбинаций, или более общую форму / [0-9] + \ / (light | dark | play) /
( любое число, за которым следует косая черта и одно из « светлый », « темный » и « play ») или даже / [0-9] + \ / \ w + /
(любое число, за которым следует косая черта и слово, также известное как [A-Za-z0-9 _] +
). Все зависит от того, насколько строгим или широким вы хотите, чтобы фильтр был.