Kuinka kopioida kansio rekursiivisesti idempotenttisesti käyttämällä cp: tä?
On joulukuu 1, 2020 by adminKun käytän
cp -R inputFolder outputFolder
tulos on asiayhteydestä riippuvainen :
- jos
outputFolder
ei ole, se on luodaan, ja kloonatun kansion polku onoutputFolder
. - jos
outputFolder
on olemassa, luotu klooni ollaoutputFolder/inputFolder
Tämä on kamalaa , koska haluan luoda asennuskoodin, ja jos käyttäjä suorittaa sen kahdesti vahingossa, hän luo outputFolder
ensimmäisen kerran, ja toisella kerralla kaikki tavarat luodaan uudelleen kohdassa outputFolder/inputFolder
.
- Haluan aina ensimmäisen toiminnan: luo klooni alkuperäisen vieressä (sisarena).
- Haluan käyttää
cp
kannettavana (esim. MINGW eirsync
lähetetty) - Tarkistin
cp -R --parents
, mutta tämä luo polun uudestaan hakemistopuun asti (joten klooni ei oleoutputFolder
, muttasome/path/outputFolder
) -
--remove-destination
tai--update
jos 2 ei muuta mitään, asiat kopioidaan siltioutputFolder/inputFolder
Onko siellä on tapa tehdä tämä tarkistamatta ensin outputFolder
(jos kansiota ei ole …) olemassaoloa tai rm -rf outputFolder
?
Mikä on sovittu, kannettava UNIX-tapa tehdä niin?
Kommentit
vastaus
Käytä tätä:
cp -R inputFolder/. outputFolder
Tämä toimii samalla tavalla kuin sanotaan, että cp -R aaa/bbb ccc
toimii: jos ccc
ei ole, niin sitä ” luotu kopiona tiedostosta bbb
ja sen sisällöstä; mutta jos ccc
on jo olemassa, ccc/bbb
luodaan kopiona tiedostosta bbb
ja sen sisällöstä .
Melkein kaikissa bbb
-tapauksissa tämä antaa ei-toivotun käyttäytymisen, jonka mainitsit kysymyksessäsi. Tässä erityistilanteessa bbb
on kuitenkin vain .
, joten aaa/bbb
on todella aaa/.
, joka puolestaan on oikeastaan vain aaa
, mutta toisella nimellä. Joten meillä on nämä kaksi skenaariota:
-
ccc
ei ole olemassa:Komento
cp -R aaa/. ccc
tarkoittaa” luoccc
ja kopioiaaa/.
-sivunccc/.
eli kopioiaaa
osastoonccc
. -
ccc
on olemassa:Komento
cp -R aaa/. ccc
tarkoittaa” kopioiaaa/.
ccc/.
, ts. kopioiaaa
osastoonccc
.
Kommentit
- Huh, että ’ on uusi minulle, mutta se näyttää toimivan! Onko tämä dokumentoitu missä tahansa?
- Olen ’ testannut
inputFolder/.
inputFolder
ja todellakin se toimii minulle Windows / Git Bashissa. (Se ei kuitenkaan toimi vain perässä olevan/
kanssa, tarvitsen myös pisteen kauttaviivan jälkeen).Annoin +1, koska se ’ on mielenkiintoista, vaikka se ’ on todennäköisesti liian hankala käyttää sitä julkisessa koodissa:) - @IlmariJaronen sitä ei ’ ei tarvitse dokumentoida yksiselitteisesti. Seuraa selitystä ja ’ näet, kuinka se yksinkertaisesti ” noudattaa sääntöjä ” .
Vastaa
Älä kopioi kansiota, kopioi vain sen sisältö:
## Create the target directory. The -p suppresses error messages ## if the directory already exists mkdir -p outputFolder ## Copy the contents recursively, this will not recreate the parent cp -R inputfolder/* outputfolder/
Tällä tavoin varmistat, että kohdehakemisto luodaan ensimmäisen kerran, kun komentosarja suoritetaan, ja vältä toisen kerran.
Chris Down huomauttaa hyvin, että bashissa tämä ohittaa tiedostot, joiden nimi alkaa .
. Tämän välttämiseksi , voit suorittaa shopt -s dotglob
ennen yllä olevan komennon suorittamista.
Molemmat -p
mkdir
ja -R
kohteelle cp
määrittelee POSIX, joten sen pitäisi olla täysin kannettava.
Kommentit
- Huomaa: tämä ei ’ t kopioi tiedostoja, jotka alkavat
.
. Bashissa voit käyttää siihendotglob
. - Huomaa, että tämä menetelmä todennäköisesti epäonnistuu, jos syötekansiossa olevien hakemistomerkintöjen määrä on suuri, koska globaali laajennus voi ylittää komentorivin enimmäispituuden.
Vastaa
Kokeile -T
-vaihtoehto kohtaan cp
. Tämä on GNU coreutils cp
-versiossa 8.22; se ei ehkä ole kannettava sen ulkopuolella.
Kommentit
- Joo, näyttää siltä, että halusin juuri tämän:
cp -T
(cp --no-target-directory
). unix.stackexchange.com/questions/94831/… Valitettavasti minun versionicp
on paljon vanhempi. - +1 käytti tätä juuri tänään.
-u
on loistava vaihtoehto lisätä se laiskaksi.
Vastaa
Voit käyttää myös rsync
:
rsync -uav inputFolder/ outputFolder/
(huomaa kauttaviivat, varsinkin ensimmäisen jälkeen )
Vastaus
Voit käyttää iv id = ”-vaihtoehtoa -t
a7c675a4a9 ”>
-komento muodossa:
cp -R inputFolder -t outputFolder
nyt, jos kohdekansiota ei ole, se aiheuttaa virheen:
cp: failed to access ‘outputFolder’: No such file or directory
yllä oleva huomautus komento kopioi inputFolder
sen sisällön (eikä vain sen sisällön) kanssa
jos haluat Kopioida vain inputFolder
-sisällön sisältö on hankalaa (koska sinun on oltava varovainen, kun käytät kuoren heilutusta tähdellä *)
cp -R -t outputFolder/ -- inputFolder/*
jos kohdekansiota ei ole, se aiheuttaa virheen:
cp: failed to access ‘outputFolder’: No such file or directory
toimii cp (GNU coreutils) 8.23
Vastaus
Mielestäni mikään ei ole yksinkertaisempaa ja siirrettävämpää kuin rm -rf outputFolder
. Joten olen aina kiinni siitä. Ymmärrän, että kysymyksesi on erilainen, mutta mielestäni tämä on paras käytäntö.
Kommentit
- Se epäonnistuu, jos sinulla olisi erityisiä käyttöoikeuksia tai omistusoikeuksia. tavoitteessa, joka oli pidettävä. Tai jos se oli symlinkki.
- Kysymys haluaa, että
cp
-tulos on sama, sekä silloin, kun hakemistoa ei ole, että silloin, kun sitä on olemassa. Joten, mistä puhut? - OP: n antama komento
cp
ei pidä oikeuksia ’ (tai aikaleimat).
mv
siirtämästä tiedostokokoelma yhdeksi tavalliseksi?rsync
?cp
, kahdentar
-komennon välinen putkitus on mukava ja luotettava tapa kopioida puita.rsync
.tar -C input -cf - . | tar -C output -xf -
toimii.-C
muuttaa työhakemistoa, mutta se ei ole vakiovaihtoehto, joten jos sitä ’ ei tueta, sinun on suoritettava kaksi tervaa oikeat työhakemistot aluksi esimerkiksi( cd input && tar -cf - . ) | ( cd output && tar -xf - )
Jos kuitenkin ’ käsittelet Windowsia, käytän vain roaima ’ vastausta .