Это может отличаться в зависимости от вашей оболочки, но при условии, что bash:
for a in $(find /home -maxdepth 1 -type d); do mv $a/homedir/* $a/; rmdir $a/homedir; done
Запустите команду find
отдельно, чтобы убедиться, что список соответствует вашим ожиданиям, прежде чем запускать полную и удалите часть rmdir
, если вы хотите оставить пустой homedir
в каждой папке.
Если вы не превысите длину командной строки с помощью globs mv / home / * / * / home
, все будет работать. Обратите внимание, если у вас есть файлы в / home / user
, они также будут перемещены в / home
.
Переместить содержимое домашнего каталога вверх по каталогу:
cd /home
for i in */homedir; do /bin/mv $i/* $i/.. && /bin/rmdir $i; done
Вот более параноидальный сценарий, который избегает всех имен пользователей (использует "@@@" для tmp dir) , сохраняет точечные файлы, которые отбрасывает "mv $ a / homedir / *", останавливается, если каталог @@@ не согласован, и не должно иметь проблемы с длиной команды. Остающийся недостаток - патологические имена пользователей.
cd /home
ls -1 | while read user ; do # allow many user dirs without imploding
[ -d @@@ ] && { echo tmp already present, aborting 1>&2 ; exit 1 ; }
mv $user @@@
mv @@@/homedir $user
rmdir @@@ || { echo tmp dir for $user not empty, aborting 1>&2 ; exit 2 ; }
done
Подход find () является хорошим выбором, если вся команда для каждого каталога была похоронена в -exec, например:
cd /home && find -name . -o -type d -prune -print \
-exec mv '{}' @@@ ';' \
-exec mv @@@/homedir '{}' ';' \
-exec rmdir @@@ ';'
Попытка чего-то вроде "для f в $ (find ....) "
хрупок, так как оболочки сначала захотят развернуть всю эту командную строку. Показанные здесь находки зависят от того, что {} расширяется с помощью find даже внутри строк, что, я не уверен, все найдет поддержку.
или даже
cd /home && find -name . -o -type d -prune -print -exec \
sh -c 'mv {} @@@ && mv @@@/homedir {} && rmdir @@@' ';'
Тестирование:
mkdir -p {fred,jan,alice}/homedir
touch {fred,jan,alice}/homedir/.dotstuff
touch {fred,jan,alice}/homedir/stuff
let one rip (минус "cd / home ") и посмотрите, как это работает. Кажется, здесь все работает хорошо.
Решение SmallClanger может быть изменено так, что пробелы не будут проблемой. Уловка состоит в том, чтобы изменить внутренний разделитель полей Bash, который представляет собой переменную, вызываемую IFS и обычно содержит пробел и новую строку, чтобы просто содержать новую строку. Например:
IFS=$'\n'
Это изменит IFS на символ новой строки для вашей текущей оболочки.
После этого вы можете запустить команду SmallClanger или что-то подобное:
for item in $(find ./homedir -mindepth 1 -maxdepth 1 -type d); do
echo " --> \"$item\"" >&2
mv "$item" .
done
Предполагается, что ваш рабочий каталог - "/ home / {user} ".
Вы можете опустить строку" mv "при первой попытке увидеть, что содержит $ item. Если он выглядит хорошо, вы запускаете его с помощью «mv». Не забывайте двойные кавычки вокруг «$ item».
Таким образом, вы столкнетесь с проблемами только в том случае, если какой-либо из ваших путей к файлу или папке содержит символы новой строки, что я считаю гораздо более необычным, чем те, которые содержат пробелы.
Некоторая информация о внутреннем разделителе полей: Bash: внутренние переменные
Я также думаю, что вы можете заставить программу «find» выдавать свои результаты, разделенные NUL. Если возможно установить IFS на NUL, вы должны быть в безопасности практически для всего, поскольку обычно NUL не является допустимой кодовой точкой для файлов / каталогов в большинстве файловых систем. Но сам я никогда не пробовал.