cp-komento: kopioi tiedostokansiot oikein *nix-tiedostoon
Tämä artikkeli paljastaa joitain ei-ilmeisiä asioita, jotka liittyvät sovelluksen käyttöön jokerimerkit kopioitaessa epäselvää komentokäyttäytymistä cp kopioitaessa sekä menetelmiä, joiden avulla voit kopioida oikein valtavan määrän tiedostoja ohittamatta tai kaatumatta.
Oletetaan, että meidän on kopioitava kaikki /source-kansiosta /kohdekansioon.
Ensimmäisenä mieleen tuleva asia on:
cp /source/* /target
Korjataan tämä komento välittömästi seuraavasti:
cp -a /source/* /target
avain -a lisää kaikkien attribuuttien, oikeuksien kopioinnin ja lisää rekursion. Kun oikeuksien tarkkaa jäljentämistä ei vaadita, avain riittää -r.
Kopioinnin jälkeen huomaamme, että kaikkia tiedostoja ei kopioitu - tiedostot alkavat pisteellä, kuten:
.profile
.local
.mc
ja vastaavat.
Miksi näin kävi?
Koska komentotulkki käsittelee jokerimerkkejä (bash tyypillisessä tapauksessa). Oletuksena bash ohittaa kaikki pisteillä alkavat tiedostot, koska se käsittelee niitä piilotettuina. Välttääksemme tämän käytöksen meidän on muutettava käyttäytymistämme bash käyttämällä komentoa:
shopt -s dotglob
Voit varmistaa, että tämä käyttäytymismuutos jatkuu uudelleenkäynnistyksen jälkeen luomalla wildcard.sh-tiedoston tällä komennolla kansioon /etc/profile.d (Ehkä jakelussasi on eri kansio).
Ja jos lähdehakemistossa ei ole tiedostoja, kuori ei voi korvata mitään tähden sijasta, ja myös kopiointi epäonnistuu virheellä. Tätä tilannetta vastaan on vaihtoehtoja failglob и nullglob. Meidän on asetettava failglob, joka estää komennon suorittamisen. nullglob ei toimi, koska se muuntaa jokerimerkkejä sisältävän merkkijonon, joka ei löytänyt vastaavuutta, tyhjäksi merkkijonoksi (pituus nolla), joka cp aiheuttaa virheen.
Jos kansiossa on kuitenkin tuhansia tiedostoja tai enemmän, jokerimerkkimenetelmästä tulisi luopua kokonaan. Tosiasia on, että bash laajentaa yleismerkit erittäin pitkäksi komentoriviksi, kuten:
cp -a /souce/a /source/b /source/c …… /target
Komentorivin pituudella on raja, jonka saamme selville komennolla:
getconf ARG_MAX
Otetaan komentorivin enimmäispituus tavuina:
2097152
Или:
xargs --show-limits
Saamme jotain tällaista:
….
Maximum length of command we could actually use: 2089314
….
Tehdään siis kokonaan ilman jokerimerkkejä.
kirjoitetaan vain
cp -a /source /target
Ja tässä kohtaamme käyttäytymisen epäselvyyden cp. Jos /target-kansiota ei ole, saamme tarvitsemamme.
Jos kohdekansio on kuitenkin olemassa, tiedostot kopioidaan /target/source-kansioon.
Emme voi aina poistaa /target-kansiota etukäteen, koska se voi sisältää tarvitsemiamme tiedostoja ja tavoitteemme on esimerkiksi täydentää /target-kansiossa olevia tiedostoja /source-tiedostoilla.
Jos lähde- ja kohdekansiot nimettiin samalla tavalla, esimerkiksi kopioimme hakemistosta /source kansioon /home/source, voisimme käyttää komentoa:
cp -a /source /home
Ja kopioinnin jälkeen /home/source-tiedoston tiedostoja täydennetään tiedostoilla /source.
Tämä on looginen ongelma: voimme lisätä tiedostoja kohdehakemistoon, jos kansioiden nimet ovat samat, mutta jos ne ovat erilaisia, lähdekansio sijoitetaan kohteen sisään. Kuinka kopioida tiedostoja /sourcesta /target-kohtaan käyttämällä cp:tä ilman jokerimerkkejä?
Tämän haitallisen rajoituksen kiertämiseksi käytämme ei-ilmeistä ratkaisua:
cp -a /source/. /target
Ne, jotka tuntevat DOS:n ja Linuxin, ovat jo ymmärtäneet kaiken: jokaisen kansion sisällä on 2 näkymätöntä kansiota "." ja "..", jotka ovat pseudokansiolinkkejä nykyiseen ja ylempään hakemistoon.
Kun kopioidaan cp tarkistaa olemassaolon ja yrittää luoda /target/.
Tällainen hakemisto on olemassa ja se on /target
Tiedostot hakemistosta /source kopioidaan oikein kansioon /target.
Joten ripusta se lihavoituun kehykseen muistiisi tai seinälle:
cp -a /source/. /target
Tämän komennon käyttäytyminen on selkeä. Kaikki toimii ilman virheitä riippumatta siitä, onko sinulla miljoona tiedostoa vai ei yhtään.
Tulokset
Jos haluat kopioida kaikki tiedostot kansiosta toiseen, emme käytä jokerimerkkejä, on parempi käyttää niitä sen sijaan cp yhdistettynä pisteeseen lähdekansion lopussa. Tämä kopioi kaikki tiedostot, myös piilotetut, eikä epäonnistu miljoonien tiedostojen kanssa tai ilman tiedostoja.
loppusanat
vmspike ehdotti komentoversiota samanlaisella tuloksella: