2016-02-08 2 views
0

Я просматриваю результаты поиска, и я меняю каждую из этих папок, поэтому моя проблема в том, что когда я сталкиваюсь: /aaaa/logs/ и после этого: /aaaa/logs/bbb/logs, когда я пытаюсь установить mv /aaaa/logs/bbb/logs /aaaa/log/bbb/log, он не может найти папку, потому что она уже переименована. То есть вывод от find может сообщить, что имя /aaaa/logs/bbb/logs, когда скрипт ранее перемещал вывод на /aaaa/log/bbb/. Простой код:Переименование каталогов на нескольких уровнях с помощью find from bash

#!/bin/bash 
script_log="/myPath" 
echo "Info" > $script_log 
search_names_folders=`find /home/ -type d -name "logs*"` 
while read -r line; do 
     mv $line ${line//logs/log} >>$script_log 2>&1 
done <<< "$search_names_folders" 

Мое решение:

#!/bin/bash 
script_log="/myPath" 
echo "Info" > $script_log 
search_names_folders=`find /home/ -type d -name "logs*"` 
while read -r line; do 
     number_of_occurrences=$(grep -o "logs" <<< "$line" | wc -l) 
    if [ "$number_of_occurrences" != "1" ]; then 
     real_path=${line//logs/log} ## get the full path, the suffix will be incorrect 
     real_path=${real_path%/*} ## get the prefix until the last/
     suffix=${line##*/} ## get the real suffix 
     line=$real_path/$suffix ## add the full correct path to line 
     mv $line ${line//logs/log} >>$script_log 2>&1 
    fi 
done <<< "$search_names_folders" 

Но его плохая идея, Кто-нибудь есть другие решения? Спасибо!

+0

'find' не является частью bash, и bash не имеет ничего общего с порядком его вывода. –

+1

Кроме того ** ** ** ... стараюсь написать ясно. Есть вещи, которые можно простить из-за того, что они не носители языка, но использование «bcs» для «потому что» не является одним из них. –

+1

Кроме того, захват 'search_names_folders' в скалярной переменной просто неверен. Имена файлов могут содержать любой символ, отличный от NUL, ** включая ** новые строки, поэтому вы не можете определить разницу между новой строкой, которая разделяет два файла или новую строку, которая фактически является частью имени файла. Единственный способ точно представлять список произвольных имен файлов внутри переменной оболочки - для этой переменной быть массивом. Подумайте, кто-то делает 'mkdir -p '$' \ n/etc/passwd \ n/logs'' - это может испортить весь ваш день, если вы запустите скрипт, который удаляет все. –

ответ

2

Используйте опцию -depth для find. Это заставляет его обрабатывать содержимое каталога до того, как он обработает сам каталог.

+0

Хех - ты прав. Теперь я чувствую себя глупо. :) –

+0

... хотя это не единственное исправление, которое необходимо, поскольку код OP в настоящее время запускает подстановку всюду по пути не только по имени файла листа. –

+0

... Таким образом, если у них есть 'hello/logs/world/logs', их первый' mv' попытается переименовать его в 'hello/log/world/log', в отличие от переименования в' hello/logs/мир/журнал' первый. –

Смежные вопросы