Hoe verplaats ik alle bestanden van de huidige directory naar de bovenliggende directory?
Hoe verplaats ik alle bestanden van de huidige directory naar de bovenste directory in linux?
Ik heb zoiets als mv *.*
geprobeerd, maar dat werkt niet.
Hoe verplaats ik alle bestanden van de huidige directory naar de bovenste directory in linux?
Ik heb zoiets als mv *.*
geprobeerd, maar dat werkt niet.
Het commando dat u zoekt is
mv * .[^.]* ..
of (zie hieronder voor meer info):
(shopt -s dotglob; mv -- * ..)
Uitleg: het mv
commando verplaatst bestanden en directories. Het laatste argument voor mv
is het doel (in dit geval de map één stap “hoger” in de boom, ..
). De argumenten daarvoor zijn de bronbestanden en -directories. De asterisk (*
) is een wildcard die overeenkomt met alle bestanden die niet beginnen met een punt. Bestanden die beginnen met een punt (dotfiles) zijn “verborgen”. Ze worden gematched met het patroon .[^.]*
(zie bewerking hieronder).
Zie de manpage waarnaar ik linkte voor meer informatie over mv
.
.[^.]*
in plaats van .*
?Zoals Chris Johnsen correct opmerkt: het patroon .*
komt ook overeen met .
en ..
. Aangezien je die niet wilt (en kunt) verplaatsen, is het beter om een patroon te gebruiken dat overeenkomt met elke bestandsnaam die begint met een punt uitgezonderd die twee. Het patroon .[^.]*
doet precies dat: het komt overeen met elke bestandsnaam (1) die begint met een punt (2) gevolgd door een teken dat niet een punt is (3) gevolgd door nul of meer willekeurige tekens.
Zoals Paggas wijst , zouden we ook het patroon .??*
moeten toevoegen om overeen te komen met bestanden die met twee punten beginnen. Zie zijn antwoord voor een alternatieve oplossing met find
.
Arjan’s antwoord noemt shopt
om al die problemen met dotfiles te omzeilen. Maar dan is er nog steeds het probleem met bestanden die met een streepje beginnen. En het vereist drie commando’s. Toch vind ik het een goed idee. Ik stel voor om het als volgt te gebruiken:
(shopt -s dotglob; mv -- * ..)
Dit voert shopt
uit in een subshell (dus geen tweede oproep aan shopt
nodig) en gebruikt --
zodat bestanden die beginnen met een streepje niet worden geïnterpreteerd als argumenten voor mv
.
Kort antwoord: gebruik
find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +
Lang antwoord:
Het commando
mv * .* ..
zal niet werken, aangezien .*
kan overeenkomen met .
en ..
. Maar het commando
mv * .[^.]* ..
zal ook niet werken, aangezien .[^.]*
niet overeenkomt met bijvoorbeeld ..filename
! Wat ik in plaats daarvan doe is
mv * .[^.] .??* ..
, wat overeenkomt met alles behalve .
en ..
. *
komt overeen met alles dat niet begint met een .
, .[^.]
komt overeen met alle 2 karakter bestandsnamen beginnend met een punt behalve ..
, en .??*
komt overeen met alle bestandsnamen beginnend met een punt met minstens 3 karakters.
Beter nog, je kunt
find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +
gebruiken, waardoor de lelijke glob hacks in mv * .[^.] .??* ..
vermeden worden!
De mv mist de functionaliteit om verborgen bestanden te verplaatsen bij gebruik van *
- dus waarom niet in plaats daarvan copy gebruiken?
cp -rf . ..
rm -rf *
Geen behoefte aan ingewikkelde oplossingen van dotglobbing en het gebruik van find commando’s.
rsync -a --remove-source-files . ..
rsync
is een uiterst krachtig hulpprogramma voor het kopiëren van bestanden, dat in het algemeen wordt gebruikt voor het uitvoeren van efficiënte incrementele back-ups en spiegelservers op afstand.
Met het bovenstaande commando vertellen we rsync
om de inhoud van .
te kopiëren naar ..
De switch -a
zet recursie aan in .
submappen en zet enkele andere gebruikelijke opties aan.
De switch --remove-source-files
vertelt rsync om de bronbestanden te verwijderen na een succesvolle kopie, m.a.w. het laat rsync zich gedragen zoals het mv
commando.
Dit geminimaliseerde commando werkt op de meeste moderne shells:
\mv -- {,.{[^.],??}}* ..
Anders genoemd is een portable oplossing:
\mv -- * .[^.] .??* ..
Features:
\ voorkomt dat aliassen mv ongewenst veranderen.
– voorkomt dat bestandsnamen met koppeltekens (-xyz) worden geïnterpreteerd als command-line argumenten.
.[^.] komt overeen met alle bestandsnamen van twee tekens die beginnen met . behalve ..
.???* komt overeen met alle andere bestandsnamen van drie tekens of langer.
Naïeve implementaties:
Het volgende slaat verborgen UNIX-bestandsnamen over, die beginnen met . (.bashrc).
Het volgende komt overeen met … dat recursief probeert om elke directory uiteindelijk helemaal terug te verplaatsen naar / in … van de huidige werkdirectory ($PWD of pwd). Nooit gebruiken.
Uiteindelijk zal het proberen met mv .
mislukken omdat mv de directory waar je nu in zit niet kan unlinken. Je zou mv * ..
kunnen gebruiken om de bestanden in de cwd te verplaatsen.
Het is correcter om het patroon * .[!.] .??*
te gebruiken dan * .[^.] .??*
omdat het eerste ook werkt met oudere shells zoals ksh88:
mv -- * .[!.] .??* ..
--
voorkomt problemen als je een bestandsnaam hebt die begint met -
*
komt overeen met alle bestandsnamen die niet beginnen met een .
.
die je kunt/moet verplaatsen .[!.]
komt overeen met alle twee karakters bestandsnamen die niet beginnen met een .
.??*
die je kunt/moet verplaatsen .
komt overeen met alle bestandsnamen van twee tekens die beginnen met een .[^.]
..
komt overeen met alle bestandsnamen van drie tekens (of langer) die beginnen met een .^
Met ksh88, zal het bestandsnaampatroon 0x6& in feite overeenkomen met de bestandsnamen 0x6& (die altijd bestaat) en 0x6& (die waarschijnlijk niet bestaat), met een effect tegengesteld aan wat gewenst is.
mv * .??* ../.
*
krijgt alle niet-stip bestanden. .??*
krijgt alle . bestanden die minstens drie bytes lang zijn, wat werkt voor alle legitieme bestanden. Alles wat overblijft wil je waarschijnlijk toch rm
in plaats van mv
.
De ../.
biedt geen directe voordelen ten opzichte van ..
, maar bij het doen van een move-to-directory is het een zeer goede gewoonte om aan te wennen, omdat het zal mislukken, zoals je wilt, als er iets mis is met het pad. Bijvoorbeeld, mv xyz bletch
, waar je denkt dat bletch
een directory is, kan je zekerder maken met mv xyz bletch/.
.
Find en grep werken ook. Dit soort structuur kan handig zijn als je bestanden wilt selecteren op meer ingewikkelde criteria door find en grep aan te passen.
find -maxdepth 1 | egrep '^./.' # Returns all files
mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..
Ik denk dat de eenvoudigste oplossing voor het verplaatsen van alle bestanden naar hun bovenliggende dir. zou zijn
mv "`ls`" ../
of, Als er verborgen bestanden / mappen
gebruik:
mv "`ls -a`" ../ 2>/dev/null
Ook, stel dat je de inhoud van een map wilt verplaatsen naar een van zijn interne mappen tony(zeg)
gebruik:
mv "`ls -a`" /tony 2>/dev/null
Note:
"`ls -a`"
Om de bestanden te verplaatsen waar spaties in staan.
2>/dev/null
Is om de waarschuwing/fout te onderdrukken omdat ls -a
de .
en ..
map ook zou afdrukken en je die niet kunt verplaatsen of kopiëren. Dus voor die mappen zal het een fout tonen (als we 2x2&/dev/null niet gebruiken) dat het ze niet kan verplaatsen en de rest zal zonder problemen verplaatst worden.
Het beste is om ls -a
te vermijden als er geen verborgen bestanden zijn en gewoon ls
te gebruiken.