Jak przenieść wszystkie foldery rodzeństwa do jednego folderu?

6

Przepraszam, że to wydaje się takie głupie pytanie, ale nie mogę sobie pozwolić na spieprzenie go.

Mam kilka takich folderów:

/ users / me / foo / oops1

/ users / me / foo / oops2

/ users / me / foo / oops3

/ users / me / foo / oops4

/ users / me / foo / bar

Niestety, nie są one tak nazwane w jednolity sposób i istnieją setki folderów ups.

Zamierzałem skopiować wszystkie foldery oops do paska. Czy istnieje prosty sposób na przeniesienie wszystkich folderów Oops do paska, który nie spowoduje problemów z przenoszeniem rekurencyjnym?

Skopiowanie plików zajęło kilka godzin. Mam nadzieję, że ruch będzie znacznie szybszy.

Nawiasem mówiąc, jest to na serwerze Linux Redhat. Mam tylko dostęp ssh.

Myślę, że jeśli to zrobię

cd foo
mv * bar

będzie problem.

jgritty
źródło
Więc jak się nazywają? Czy chcesz przenieść wszystko w Foo oprócz paska do paska?
cpast
Poprawny. Mają różne imiona.
jgritty

Odpowiedzi:

3

Niestety, zarówno odpowiedź Matta, jak i Nicole wykazuje zły styl i ulegnie zepsuciu, jeśli którykolwiek z folderów będzie zawierał pojedynczy znak spacji, znak globowania (podobny *) lub nową linię. Bieganiefor item in $(ls …) jest ogromnym błędem, który można popełnić, ponieważ prędzej czy później ugryzie ich, a iteracja nazw plików, niepoprawne ich wyświetlanie może powodować różnego rodzaju problemy.

Nigdy nie analizuj wynikuls .

W Linuksie jest narzędzie do wyszukiwania plików spełniających określone kryteria i nazywa się find:

find . -mindepth 1 -maxdepth 1 \
-type d ! -regex ".\/bar$" \
-exec mv '{}' ./bar/ \;

Pozwoli to przenieść żadnych katalogów w bieżącym katalogu roboczym, które nie są nazywane barw ./bar/. Będzie działać, nawet jeśli nazwy katalogów zawierają spacje, znaki globowania lub znaki nowej linii.

Wyrażenie regularne .\/bar$będzie pasować tylko do nazwanego katalogu ./bari jest negowane przez !.

slhck
źródło
Ale to również bardzo wolno, ponieważ działa mvraz dla każdego pliku. Przy tak wielu terminach daje wiele możliwości popełnienia błędu. bashpotrzebuje lepszego narzędzia do zastępowania, które poradzi sobie z nazwami plików ze spacjami.
Nicole Hamilton,
Tak, działa mvraz dla każdego folderu , a nie pliku. Uważam, że dzięki \+temu powinien działać szybciej i przenosić wszystkie foldery za pomocą jednego polecenia, chociaż nie wiem, czy spowodowałoby to znaczne przyspieszenie. Zgadzam się z tobą, że powinno to być znacznie łatwiejsze, ponieważ w przypadku plików w Bash najprostszy sposób robienia rzeczy nigdy nie jest właściwy, niestety. Po prostu czułem, że potrzebna jest odpowiedź, która i tak zadziała.
slhck,
Na szczęście żaden z plików nie ma * ani miejsca, ale wydaje się, że jest to ogólnie lepsza odpowiedź.
jgritty,
7

To, co proponujesz, jest dokładnie właściwe. mvjest wystarczająco mądry i powie:

mv: cannot move `bar' to a subdirectory of itself, `bar/bar'

Jednak wszystkie katalogi oopsx będą znajdować się w pasku.

Perleone
źródło
To dosłownie sprawiło, że mój dzień hahahaha brutalna siła czasami po prostu działa! (Brzytwa Ockhama)
Dai
3

Tak, masz rację, to byłby problem, ponieważ *również pasuje bar; nie możesz mvkatalogować w sobie.

Technicznym sposobem jest użycie podstawiania poleceń i pętli mvtylko do rzeczy, które nie są bar. Na przykład, bashmożesz napisać coś takiego, ale zwróć uwagę, że nie powiedzie się, jeśli trafi na nazwę zawierającą spację (ponieważ podstawianie poleceń rozbija rzeczy na słowa w spacjach).

mv $(for i in *; do if [ $i != "bar" ]; then echo $i; fi; done) bar

Ale szczerze mówiąc, jestem leniwy. Chciałbym mvbar z drogi, a potem mvwszystko do niego, a następnie przenieść go z powrotem. Przenosisz tylko łącza do systemu plików, a nie zawartość pliku, więc jest szybki. Ma to tę zaletę, że działa, jeśli masz nazwy ze spacjami.

cd foo
mv bar ../bar.save
mv * ../bar.save
mv ../bar.save bar
Nicole Hamilton
źródło
Twój skrypt nie działa, jeśli którykolwiek z katalogów zawiera spację, znak globowania lub znak nowej linii. Na przykład nazwany katalog "foo baz"będzie wyglądał jak mv foo baz bar, a następnie zawiedzie.
slhck,
Tak, tak, zauważam, że zawsze to zaznaczasz. Musisz to mieć na klawiszu makra. Ale (a) jeśli masz spacje w nazwach, prawdopodobnie wiesz, że, (b) jest to problem, bashktóry powinien zostać naprawiony (jest naprawiony w mojej powłoce C ), (c) jest to dobry powód, aby to zrobić drugi sposób, który tak naprawdę poleciłem.
Nicole Hamilton,
Prawdopodobnie istnieją setki skryptów bash na samym Super User, które pokazują te trywialne wady. To jest strona, na której powinniśmy nauczyć ludzi, jak coś osiągnąć i dostosować to do ich potrzeb. Z doświadczenia PO nie powiedziałbym, że wiedzą, że posiadanie miejsca na pierwszym miejscu jest problemem. Przynajmniej powinieneś wyraźnie wspomnieć o takich założeniach w swojej odpowiedzi (wtedy też usunęłbym głos negatywny). Więc może mógłbyś edytować swój post, aby to wyjaśnić. Ponadto, nie ma problemu z skorupki per se , to tylko problem, gdy używany jest złe podejście.
slhck,
Rozmawiałem również z doświadczonymi użytkownikami systemów Unix i Linux , gdzie zasady dotyczące „zepsutych” skryptów bash są takie same. Edytuj, aby ulepszyć lub oddaj głos / komentarz, aby wskazać braki. Proszę nie brać tego do siebie, dokładamy nie że wielu użytkowników, którzy publikują tu odpowiedzi z skryptów powłoki. Właśnie to zauważyłem.
slhck,
1
Chociaż prawdą jest, że *to pasuje bar, nie stanowi problemu, ponieważ „mv” / jądro jest wystarczająco inteligentne, aby wykryć to wystąpienie. Zamiast więc stwierdzać, że jest to problem, jest to dobry sposób na zrobienie tego (chyba że chcesz odfiltrować niektóre katalogi, ale to inne pytanie)
JvO
1

Jeśli czujesz się bezpieczniej, możesz to zrobić w BASH:

for item in `ls -d | grep -v "^bar$"`; do mv $item bar; done;
Matt
źródło
2
A co z przypadkowym dopasowaniem brzana, muchy lub kory? Służy grep -v '^bar$'do dopasowania „paska”.
Perleone,
1
Zgodzić się. Lepiej z „^ bar $”. Dzięki za zauważenie. Zaktualizowałem odpowiedź.
Matt
1
Uruchomienie ls -ddaje tylko .bieżący katalog roboczy. Jesteś pewien, że to działa? Próbowałeś już polecenia? Zobacz: Jak wyświetlić listę folderów za pomocą poleceń bash? - ponadto skrypt nie powiedzie się, jeśli którykolwiek z katalogów zawiera spację, znak nowej linii lub znak globowania w nazwie.
slhck,
-1: Jak wskazał @slhck, ta odpowiedź nie działa. I @Perleone odpowiedź „s jest lepszy.
Adrian Pronk
-1

cd do foo

mv -t bar oops[[:digit:]]

bardziej ogólnych

mv -t bar oops*
WikiWitz
źródło
haha przepraszam za literówkę
WikiWitz
2
Jednak tak naprawdę nie są nazywane ups.
jgritty