Настолько глупо, что я использовал следующий сценарий на моем сервере 19.04 в попытке переместить несколько видеофайлов в папки с префиксами:
dirs=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
shopt -s nocasematch
for file in *
do
for dir in "${dirs[@]}"
do
if [ -d "$file" ]; then
echo 'this is a dir, skipping'
break
else
if [[ $file =~ ^[$dir] ]]; then
echo "----> $file moves into -> $dir <----"
mv "$file" "$dir"
break
fi
fi
done
done
Понятия не имею, где это пошло не так, но вместо того, чтобы перемещать файлы в папки, они пошли в единый вывод ..
----> a1.ts moves into -> A <----
----> a2.ts moves into -> A <----
----> a3.ts moves into -> A <----
----> a4.ts moves into -> A <----
----> a5.ts moves into -> A <----
----> c1.ts moves into -> C <----
----> c2.ts moves into -> C <----
----> c3.ts moves into -> C <----
----> c4.ts moves into -> C <----
----> c5.ts moves into -> C <----
К счастью, я остановил процесс (CTRL + C), как только заметил, что он идет не так, как задумано, и не прошел всю папку.
Так что теперь у меня есть эти файлы A
и C
, которые меньше, чем Гб, и, судя по всему, это одно видео.
В общем объеме использования самой папки на диске не хватает 50 ГБ, но общее дисковое пространство компьютера осталось прежним. Заставить меня думать, что файлы не удалены?
Любая помощь приветствуется, спасибо :)
Редактировать: файлы фактически исчезли, остается только последний записываемый файл, все, что потребовалось, - это некоторое время, чтобы обновить информацию об использовании диска. Мораль истории, запускайте свои сценарии на фиктивных файлах раньше!
источник
A
,B
и так далее существовали перед запуском сценария? Если нет, вы просто переименовали файлы. Все файлы, имена которых начинаются сa
илиA
были переименованыA
, поэтому сохранился только последний переименованный файл, остальные перезаписываются. Для вызова переменнойdir
не создается каталог!mv "$file" "$dir/"
, с трейлингом/
; тогда, если$dir
не существует,mv
произойдет ошибка вместо переименования$file
в$dir
. Также рассмотримmv -i
иmv -n
. И всегда делайтеmkdir -p
перед переездом, для хорошей меры.Ответы:
Я думаю, что это проблема: вы должны были создать каталоги A, B, C ... Z. Если вы это сделали,
mv
команда должна была переместить файлы в эти каталоги.Но если нет,
mv
команда перемещает файлы в файлы с этими именами, A, B, C ... и я думаю, что это то, что вы сделали.Чтобы сделать шеллскрипт более безопасным, вы должны создать каталоги (если их там еще нет), прежде чем начать перемещение.
Если вы хотите, чтобы все
mv
стало еще безопаснее, вы также можете использовать-i
опциюисточник
touch
хорошим подспорьем, чтобыmkdir
избежать конфликтов в случае многократного запуска скрипта?touch
создает файл, если имя не существует. Так что он не будет делать то, что вы хотите в этом случае.mkdir -p
может справиться с использованием сценария несколько раз.mv
более безопасным, чтобы получить в привычку добавлять слэш имя цели , когда цель является каталогом т.е.mv "$file" "$dir/"
@Sudodus уже объяснил, что пошло не так, но вот более простая версия вашего сценария в следующий раз:
объяснение
for letter in {a..z}; do
:{a..z}
расширяется на все строчные буквы междуa
иz
:Так что это будет перебирать все строчные буквы, сохраняя каждую как
$letter
.dir=${letter^}
: синтаксис${var^^}
возвращает содержимое переменной$var
с первым символом в верхнем регистре (так как он имеет только один символ, это все, что нам нужно). Таким образом, если$letter
естьa
, то${letter^^}
естьA
, и, следовательно,$dir
будет верхний регистр версии текущего$letter
.mkdir -p -- "$dir"
: создать каталог. Если он уже существует, ничего не делать (-p
). Знак--
обозначает конец параметров и полезен для защиты от имен, начинающихся с-
.mv -- "$letter"* "${letter^}"* "$dir"
: переместить каждый файл (или каталог) в соответствующую цель.Проблема в том, что он также будет перемещать любые каталоги, которые у вас могут быть. Он не будет перемещать целевые каталоги, потому что либо они еще не существуют, либо вы попытаетесь переместить их в себя, но любые существующие каталоги, которые не являются целевыми, будут перемещены.
Если это проблема, вам придется сделать что-то вроде этого:
источник
${letter^}
и${letter^^}
, и если они идентичны, зачем использовать${letter^^}
вместо$dir
?${var^}
использует только${var^^}
заглавные буквы , а все буквы - заглавные. Это не имеет никакого значения здесь, так как$letter
имеет только одну букву.$dir
вmv
команду косую черту каталога . (В его нынешнем виде он потерпит неудачу, если файл уже существует с заглавным именем из одной буквы)Вместо проверки каждого файла по массиву словаря, который создает много итераций, вы можете сопоставлять файлы с шаблонами.
Очень простой вид:
источник
Защита в вашем .bashrc:
источник
-n Do not overwrite an existing file. (The -n option overrides any previous -f or -i options.)
так, имеет ли значение, что тег -n будет перед следующими тегами? Параметр --backup = numbered создаст двойное число каждого права, не слишком ли это излишне (и потребляет много энергии) при работе с видеофайлами очень большого размера (терабайтами). Благодарность !Для записи, некоторые способы остановить
mv
перезапись существующих файлов:Если вы хотите перейти в каталог, добавьте косую черту к цели, т.е. используйте
mv "$file" "$dir"/
вместоmv "$file" "$dir"
. Если$dir
не существует или не каталог,mv
будет жаловаться:Похоже, это делает системный вызов
rename("a", "z/")
, поэтому он должен быть защищен от уязвимостей, связанных с проверкой на время использования, в случае, если кто-то обрабатывает один и тот же набор файлов в одно и то же время.В качестве альтернативы используйте
mv -t "$dir" "$file"
. Опять же, он будет жаловаться, если$dir
не каталог.Используйте
-n
параметр, чтобы предотвратить перезапись существующих файлов:Это не помешает ему переименовать первый файл, но не помешает другим.
Кажется, это вызывает равнину
rename()
, поэтому может быть небезопасно при одновременной обработке. (Там естьrenameat2()
поддержка флага для предотвращения перезаписи.)источник
Хотя, очевидно, это не так, возможно, вы могли бы сделать это и не потерять файлы. Для этого потребуется одна из двух вещей:
Файловые системы Unix позволяют нескольким элементам каталога обращаться к одному и тому же содержимому файла . Это называется « жесткой связью ». Вы можете создавать жесткие ссылки с помощью
ln
команды, без общей-s
(мягкой / символической) опции. Пока существует хотя бы одна жесткая ссылка на содержимое файла, она не будет повторно использоваться файловой системой.(Примечание: разрешения обычно применяются к содержимому файла, а не к записи каталога. Вот почему обычный пользователь может иногда удалять файл, принадлежащий ему
root
, но не записывать его. Операция удаления изменяет папку, а не сам файл. )Файловая система также не будет повторно использовать содержимое файла, если хотя бы один процесс имеет открытый файл. Даже если нет записи в каталоге, файловая система не будет считать пространство свободным, пока ни один процесс не откроет его. Файл можно восстановить из виртуальной файловой системы
/proc/<pid>/fd
,root
пока файл остается открытым. (Спасибо @fluffysheap.)источник