Ошибка mv command "уже существующий файл"

Я использую простой скрипт для создания некоторых каталогов. Поиск определенных файлов по имени, а затем перемещение их в созданные мной каталоги. Код, который я использую, приведен ниже:


mkdir ./3DBGB_run mkdir ./run_optimization mkdir ./run_optimization/project_mesh mkdir ./run_optimization/CFD_optimized find . -name '*.template' -exec mv -i {} ./3DBGB_run \; find . -name '3dbgbinput.*.dat' -exec mv -i {} ./3DBGB_run \; find . -name 'controlinputs.*.dat' -exec mv -i {} ./3DBGB_run \; find . -name '*.iec' -exec mv -i {} ./run_optimization/project_mesh \; find . -name '*.trb' -exec mv -i {} ./run_optimization/project_mesh \; find . -name '*.py' -exec mv -i {} ./run_optimization \;** 

Код запускается и перемещает файлы в нужные каталоги, но затем он также отображает сообщение об ошибке для каждого файла, который «не может перемещать файл, потому что это тот же файл»,

Вы должны избегать поиска в целевом каталоге. Так что вы можете добавить ! -path $TARGET_DIR ! -path $TARGET_DIR например:

 find . -name '*.template' ! -path "*3DBGB_run/*" -exec mv -it ./3DBGB_run {} \+ 

find находит ваши файлы дважды: в том месте, где они начали, и куда вы их переместили. Это означает, что он заканчивается:

 mv -i 3DBGB_run/x.template 3DBGB_run/x.template 

и выдает ошибку, которую вы видите.

find видит файлы «вживую», поскольку он идет – он не создает список заранее, а затем запускает команду для всего, что есть в списке. Порядок просмотра файлов и каталогов не определен (скорее всего, это происходит из файловой системы), поэтому это произойдет для каждого файла, который был проверен перед каталогом, в который вы его переместили.

Поскольку find не знает, что вы делаете в -exec , он не может его компенсировать. Вы можете сделать пару вещей об этом:

  1. Исключите каталоги из поискового пространства: find . -name '*.template' -path "./3DBGB_run" -prune -o -exec mv -i {} ./3DBGB_run \; find . -name '*.template' -path "./3DBGB_run" -prune -o -exec mv -i {} ./3DBGB_run \; , Часть -path соответствует директории, в которую вы перемещаете вещи, и -prune затем исключает это дерево из рекурсии. -o приводит к тому, что остальная часть команды (ваш исходный -exec ) запускается в остальное время. Команда никогда не запускается в файлах внутри каталога. (Это явный пример в руководстве по GNU find )
  2. Создайте список перед переходом. В некоторых случаях это может быть лучше, но если ваши имена файлов имеют пробелы или другие символы IFS это не так хорошо работает. Если это не применяется, что-то вроде:

     files=$(find . -name '*.template') mv "${files[@]}" 3DBGB_run 

    также будет работать.


Когда вы используете find -exec , завершая команду с помощью + вместо ; заставит find запустить минимальное количество команд, собирая несколько аргументов в каждом исполнении, что является более эффективным. Иногда это не работает для определенной команды, но здесь все будет хорошо. Если это одноразовая команда, это не имеет большого значения, но если вы запустите ее много, то сохранение процессов позволит сэкономить время.