Andreas прав это src/*
расширен оболочкой. Однако, даже если Вы не указываете подстановочный знак cp
мог бы все еще пропустить Ваши недавно созданные файлы, потому что будет состояние состязания между cp
процесс, получающий доступ к каталогу и Вам (на самом деле, процесс, который создает файлы от Вашего имени), изменение каталога.
Что касается реализации CP GNU, это действительно получает список записей каталога перед фактическим копированием (см. copy_dir
функционируйте здесь).
Ваш сценарий кодируется опасным способом.
Во-первых, я предполагаю, что Вы используете оболочку Bash, так как Вы отметили ее '/bash' и '/for'.
В моем ответе я заключу в кавычки этому замечательному руководству Bash, которое является, вероятно, лучшим источником для приобретения знаний Bash из там.
1) Никогда не используйте Замену Команды, ни одного вида, без кавычек. Здесь существует главная проблема: использование неупомянутого расширения для разделения вывода на аргументы.
Специфически говорящий, это $(find $DIRWORK -type d -name work)
и $(find $DIR -type f)
подвергнется Word Splitting, таким образом если find
находит файл с пробелами на его имя, т.е. "имя файла", результат разделения слова Bash передаст 2 аргумента в пользу for
команда для итерации, т.е. один для "файла" и один для "имени". В этом случае Вы хотите надеяться, что Вы получите "файл: Никакой такой файл или каталог" и "имя: Никакой такой файл или каталог", вместо того, чтобы потенциально нанести ущерб им, если они действительно существуют.
2) Условно, переменные среды (ПУТЬ, РЕДАКТОР, ОБОЛОЧКА...) и внутренние переменные оболочки (BASH_VERSION, СЛУЧАЙНЫЙ...), полностью использованы для своей выгоды. Все другие имена переменной должны быть нижним регистром. Так как имена переменной чувствительны к регистру, эта конвенция старается не случайно переопределять переменные окружения и внутренние переменные.
Ваши повреждения каталога $DIRWORK, что конвенция, и это также закрыло кавычки, таким образом если мы позволяем DIRWORK='/path/to/dir1 /path/to/dir2'
, find
изучит два различных каталога, когда $DIRWORK закроется кавычки. Предмет использования кавычек очень важен в Bash, таким образом, Вы должны "Двойная кавычка" каждое расширение, а также что-либо, что могло возможно содержать специальный символ, например, "$var", "$", "$ {массив}", "$ (команда)". Bash рассматривает все в 'одинарных кавычках' как литерал. Изучите различие между 'и "и'. Посмотрите Кавычки, Аргументы, и Вы могли бы также хотеть смотреть на эту ссылку: http://wiki.bash-hackers.org/syntax/words
Это - более безопасная версия Вашего сценария, который я рекомендую Вам использовать вместо этого:
my_home="/root/mydir"
my_dir="$my_home/var"
dir_work="$my_home/Local"
while IFS= read -r -d '' f; do
# I'm guessing that you also want to ignore stderr;
# this is where the 2>&1 came from.
if lsof -n "$f" | grep '[a-z]' > /dev/null 2>&1; then
echo "hey, I'm safer now!"
fi
done < <(find "$dir_work" -type f -print0)
while IFS= read -r -d '' f; do
echo "2"
done < <(find "$dir_work" -type d -name 'work' -print0)
Как Вы видите, IFS
переменная установлена быть emtpy, таким образом предотвратив read
от обрезки продвижения и конечных пробелов от строки. read
управляйте использует пустую строку ( -d ''
) как разделитель, для чтения, пока это не достигает \0. find
потребности, которые будут изменены соответственно, поэтому это использует -print0
опция разграничить ее данные с \0 вместо новой строки - который, удивительно и злонамеренно, может быть часть имени файла. Разделение такого файла \n в две части взломает наш код.
Вы могли бы хотеть читать о Замене Процесса, если Вы не понимаете мой сценарий полностью.
Предыдущий ответ, который указал это find ... | while read name; do ...; done
должен использоваться для чтения find
s вывод может быть также плохим. while
цикл выше выполняется в новой подоболочке с ее собственной копией переменных, скопированных с родителя. Эта копия затем используется, за что Вам нравится. Когда while
цикл закончен, копия подоболочки отбрасывается, и исходные переменные родителя не изменились.
Если Вы нацеливаетесь при изменении некоторых переменных в этом while
цикл и использует их впоследствии в родителе, рассматривает использование более безопасного сценария, выше которого предотвратит потерю данных.
Этот код
for i in $(find $DIRWORK -type d -name work); do
echo "2"
done
сначала выполнит эту строку
find $DIRWORK -type d -name work
ожидайте до find
законченное выполнение и затем берет вывод и отложило его в for
цикл
for i in the output of find; do
echo "2"
done
только затем для цикла начнет выполняться.
Таким образом, если find
занимает много времени для окончания for
цикл должен ожидать долгое время, прежде чем он сможет запуститься.
Попытайтесь синхронизировать find
команда в интерактивной подсказке
$ time find $DIRWORK -type d -name work
и посмотрите, сколько времени это берет.
Также примечание: Вы не должны использовать a for
цикл к циклу по именам файлов. Используйте a while
цикл с read
как это:
find $DIRWORK -type d -name work | while read name; do
echo "2"
done
Считайте это для получения дополнительной информации.
Премия: это выполняется while
цикл параллельно к find
. Это означает while
цикл выполнит одно повторение как только find
распечатывает одну строку. Это не должно ожидать find
закончить выполняться.
something=$(basename "filename with spaces")
. – 23.04.2013, 00:43