Перемістіть кожен файл, який не є каталогом


14

У мене є каталог, який я намагаюся очистити, який містить і файли, і підкаталоги. Я намагаюся зробити це просто: перемістіть усі файли в інший каталог, але залиште всі підкаталоги такими, якими вони є.

Я думаю про щось на кшталт:

mv [*_but_no_dirs] ./other_directory

Здається, що має бути простий спосіб зробити це за допомогою макіяжів *та регулярних виразів ...

У когось є ідеї?


1
Отже, перемістіть усі файли в підпапках, але ігноруйте будь-які у підкаталогах?
Вільф

@Wilf: Саме так.
питання

2
У zsh ви могли б зробити mv **/*(.) ./other_directory- findхоча з bash вам потрібно буде вдатися до зовнішніх команд, як-от .
godlygeek

Відповіді:


12

Regex тут не бере участь. Замісні знаки в баші (як і більшість інших оболонок) відповідають файлам лише на основі імен файлів, а не на основі типу файлу чи інших характеристик. Існує один спосіб зіставлення за типом: додавання/ в кінці шаблону дозволяє лише відповідати каталогів або символічним посиланням на каталоги. Таким чином, ви можете переміщувати каталоги, потім переміщувати те, що залишилося, і переміщувати каталоги назад - громіздко, але це працює.

tmp=$(TMPDIR=.. mktemp -d)
mv -- */ "$tmp"
mv -- * "$tmp"/other_directory/
mv "$tmp"/* .
rmdir "$tmp"

Стандартний спосіб зіставлення файлів за типом - дзвінок find .

find . -name . -o -type d -prune -o -exec sh -c 'mv "$@" "$0"' other_directory/ {} +

У zsh ви можете використовувати глобальні класифікатори для відповідності файлів за типом. .Відбіркові матчі регулярних файлів; використовувати ^/для узгодження всіх не-каталогів, або-^/ для включення символьних посилань на каталоги.

mv -- *(.) other_directory/

У будь-якій оболонці, ви можете просто петлю.

for x in *; do
   if ! [ -d "$x" ]; then
     mv -- "$x" other_directory/
   fi
done

8

Ви можете використовувати щось подібне

find . -maxdepth 1 \( ! -type d \) -exec sh -c 'mv  "$@" MYDIR' _ {} \;

Спочатку ми використовуємо findдля огляду лише поточну дирекцію, потім ігноруємо каталоги, використовуючи, ! -type d нарешті, ми виконуємо shта переміщуємо все до місця призначення. Ви можете спробувати {} +в кінці, який буде швидшим.


2
Трохи пояснень, будь ласка ...
питання

1
@Questionmark Я оновив відповідь і додав пояснення. Також варто відвідати mywiki.wooledge.org/UsingFind
Valentin Bajrami

Чому ви пропонуєте, -exec sh -c 'mv "$@" MYDIR' _ {} \;а не -exec mv {} MYDIR \;? Просто , щоб отримати що - то , що можна раціоналізувати шляхом зміни \;до +? Ви можете зробити це за допомогою -exec mv -t MYDIR {} +форми.
Скотт

@Scott Я не мав уявлення про -tпрапор. У відповідь я також пояснив, що +швидше, але не всі findверсії підтримують це. Таким чином, наведений вище код в значній мірі сумісний з будь-якою findабо оболонкою, яка використовується.
Валентин Байрамі

1
@ val0x00ff: "... вищевказаний код в значній мірі сумісний з будь-якими findабо оболонками, які використовуються." Щоправда, але так є find … -exec mv {} MYDIR \;, і це використовує менше ресурсів, ніж … -exec sh -c 'mv "$@" MYDIR' _ {} \;.
Скотт

0

Це потенційно трохи небезпечно, але

cp * destination/
rm *

Оскільки і cp, і rm не працюватимуть в каталогах без перемикача -r.


-1

Я б запропонував просто зробити mv *.* destination/з пунктом призначення / бути папкою, в яку ви переходите.



2
Імена каталогів можуть містити "крапка", а імена файлів можуть виключати її (і часто це роблять), тому *.*вони переміщуватимуть деякі каталоги та залишатимуть деякі файли, а це не те, що хотів запитувач.
dave_thompson_085

Вибачте, але це абсолютно неправильно. Він просто перемістить що-небудь із крапкою у своєму імені і нічого не перемістить без одного. Точки жодним чином не ексклюзивні для файлів, і файли їх також не вимагають, тому це просто перемістить випадковий вибір файлів і каталогів.
тердон

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.