Mam duży katalog zawierający podkatalogi i pliki, które chcę kopiować rekurencyjnie.
Czy jest jakiś sposób, aby powiedzieć cp, że powinien wykonać operację kopiowania w kolejności wielkości pliku, aby najpierw skopiować najmniejsze pliki?
Aby mieć pewność, że nie występuje problem XY , czy możesz wyjaśnić, dlaczego chcesz to zrobić?
złotowłosa
4
@ TAFKA'goldilocks '- Mam dużo plików wideo i chciałbym przetestować jakość każdego katalogu. Najmniejszy film da mi szybkie wskazanie, czy reszta plików też jest zła.
nbubis
Odpowiedzi:
10
Wykonuje to całą pracę za jednym razem - we wszystkich katalogach potomnych, wszystko w jednym strumieniu bez problemów z nazwami plików. Skopiuje od najmniejszego do największego każdego pliku, który masz. Będziesz musiał, mkdir ${DESTINATION}jeśli jeszcze nie istnieje.
find .!-type d -print0 |
du -b0 --files0-from=/dev/stdin |
sort -zk1,1n|
sed -zn 's/^[^0-9]*[0-9]*[^.]*//p'|
tar --hard-dereference --null -T /dev/stdin -cf -|
tar -C"${DESTINATION}"--same-order -xvf -
Ale wiesz co? Nie robi to pustych katalogów potomnych. Mógłbym dokonać przekierowania przez ten rurociąg, ale to tylko warunek wyścigu, który czeka na to, aby się wydarzyć. Najprostszy jest prawdopodobnie najlepszy. Po prostu zrób to później:
find .-type d -printf 'mkdir -p "'"${DESTINATION}"'/%p"\n'|./dev/stdin
Lub, ponieważ Gilles ma bardzo dobry punkt w swojej odpowiedzi, aby zachować uprawnienia do katalogu, powinienem również spróbować. Myślę, że to zrobi:
@ TAFKA'goldilocks 'Potraktuję to jako komplement. Dziękuję bardzo.
mikeserv
15
Oto szybka i brudna metoda rsync. W tym przykładzie uważam, że wszystko poniżej 10 MB jest „małe”.
Najpierw przenieś tylko małe pliki:
rsync -a --max-size=10m srcdir dstdir
Następnie przenieś pozostałe pliki. Przeniesione wcześniej małe pliki nie zostaną ponownie skopiowane, chyba że zostaną zmodyfikowane.
rsync -a srcdir dstdir
Od man 1 rsync
--max-size=SIZE
This tells rsync to avoid transferring any file that is larger
than the specified SIZE.The SIZE value can be suffixed with a
string to indicate a size multiplier, and may be a fractional
value (e.g."--max-size=1.5m").This option is a transfer rule, not an exclude, so it doesn’t
affect the data that goes into the file-lists, and thus it
doesn’t affect deletions.It just limits the files that the
receiver requests to be transferred.The suffixes are as follows:"K"(or "KiB") is a kibibyte
(1024),"M"(or "MiB") is a mebibyte (1024*1024), and "G"(or
"GiB") is a gibibyte (1024*1024*1024).If you want the multi‐
plier to be 1000 instead of 1024, use "KB","MB", or "GB".(Note: lower-case is also accepted for all values.)Finally,if
the suffix ends in either "+1" or "-1", the value will be offset
by one byte in the indicated direction.Examples:--max-size=1.5mb-1 is 1499999 bytes, and
--max-size=2g+1 is 2147483649 bytes.
Oczywiście kolejność przesyłania plików po pliku nie jest ściśle od najmniejszej do największej, ale myślę, że może to być najprostsze rozwiązanie, które spełnia ducha Twoich wymagań.
Tutaj otrzymujesz 2 kopie twardych linków, a miękkie linki są przekształcane w rzeczywiste pliki dla dwóch kopii każdego z nich. Zrobiłbyś o wiele lepiej z --copy-dest=DIRi / lub --compare-dest=DIRmyślę. Wiem tylko, bo musiałem dodać --hard-dereferencesię do tarpo zaksięgowaniu własną odpowiedź, ponieważ brakowało mi linki. Wydaje mi się, że i rsynctak zachowuje się bardziej specyficznie dla lokalnych systemów plików z tymi innymi - użyłem go z kluczami USB i zalałoby to magistralę, chyba że ustawię limit przepustowości. Myślę, że powinienem był użyć jednego z tych innych.
mikeserv
1
+1 za „szybką i brudną metodę”. Prostsze jest zwykle lepsze przynajmniej do celów automatyzacji i przyszłej konserwacji. Myślę, że to jest całkiem czyste. „Elegancki” kontra „kludgy” i „solidny” kontra „niestabilny” mogą czasami kolidować jako cele projektowe, ale istnieje równowaga, którą można osiągnąć, i myślę, że jest elegancki i dość solidny.
Wildcard
4
Nie cpbezpośrednio, to znacznie przekracza jego możliwości. Ale możesz ustawić wywoływanie cpplików we właściwej kolejności.
Zsh wygodnie umożliwia sortowanie plików według rozmiaru za pomocą kwalifikatora glob . Oto fragment kodu zsh, który kopiuje pliki w kolejności rosnącej od dolnej /path/to/source-directorydo dolnej /path/to/destination-directory.
cd /path/to/source-directory
for x in**/*(.oL);do
mkdir -p /path/to/destination-directory/$x:h
cp $x /path/to/destination-directory/$x:h
done
Zamiast pętli możesz użyć zcpfunkcji. Najpierw jednak musisz utworzyć katalog docelowy, co można zrobić w tajemniczym oneliner.
autoload -U zmv; alias zcp='zmv -C'
cd /path/to/source-directory
mkdir **/*(/e\''REPLY=/path/to/destination-directory/$REPLY'\')
zcp -Q '**/*(.oL)''/path/to/destination-directory/$f'
To nie chroni własności katalogów źródłowych. Jeśli chcesz, musisz zapisać odpowiedni program do kopiowania, taki jak cpiolub pax. Jeśli to zrobisz, nie musisz dzwonić cpani zcpdodatkowo.
cd /path/to/source-directory
print -rN **/*(^.)**/*(.oL)| cpio -0-p /path/to/destination-directory
Nie wydaje mi się, żeby można to cp -rzrobić bezpośrednio. Ponieważ może upłynąć nieokreślony czas, zanim pojawi się kreator find/ awkrozwiązanie, oto krótki skrypt w perlu:
Argumenty powinny być ścieżkami bezwzględnymi ; ~lub cokolwiek innego, co powłoka rozwija na ścieżkę absolutną, jest w porządku.
Jeśli dodasz trzeci argument (cokolwiek, z wyjątkiem literału 0), zamiast go skopiować, wydrukuje standardowy raport o tym, co by zrobił, z rozmiarami plików w bajtach, np.
prawdopodobnie jest to jedyna poprawna odpowiedź tutaj. Czy to był ... tytuł - właśnie się zmieniłem ...? Moje okno przeglądarki jest wywoływane, cp - copy smallest files first?ale tytuł postu jest po prostu. W copy smallest files first?każdym razie opcje nigdy nie zaszkodzą mojej filozofii, ale ty i David jesteście jedynymi, którzy skorzystali, cpa ty jesteś jedynym, który to zrobił.
mikeserv
@mikeserv Jedynym powodem, dla którego użyłem cpbyło to, że jest to najprostszy sposób na zachowanie właściwości pliku * nix w perlu (zorientowanym na wiele platform). Powodem, dla którego wyświetla się pasek przeglądarki, cp - jest funkcja SE (niemądra), w wyniku której najpopularniejszy z wybranych tagów pojawia się przed rzeczywistym tytułem.
goldilocks,
Ok, wycofuję komplement. Nie bardzo, często nie widzisz, pearljak wychodzi z tutejszej stolarki.
mikeserv
1
inną opcją byłoby użycie cp z wyjściem du:
oldIFS=$IFS
IFS=''for i in $(du -sk *mpg | sort -n | cut -f 2)do
cp $i destination
done
IFS=$oldIFS
Można to nadal zrobić w jednym wierszu, ale podzieliłem go, abyś mógł go przeczytać
To również nie wydaje się obsługiwać rekurencji przez hierarchię katalogów opisaną przez OP.
cpugeniusmv
1
@cugugususmv Prawidłowo ... W jakiś sposób przegapiłem część rekurencyjną ... Mógłbym to zmodyfikować, aby obsługiwać rekurencję, ale myślę, że w tym momencie inne odpowiedzi lepiej sobie radzą. Zostawię to tutaj na wypadek, gdyby pomogło to komuś, kto zobaczy pytanie.
Odpowiedzi:
Wykonuje to całą pracę za jednym razem - we wszystkich katalogach potomnych, wszystko w jednym strumieniu bez problemów z nazwami plików. Skopiuje od najmniejszego do największego każdego pliku, który masz. Będziesz musiał,
mkdir ${DESTINATION}
jeśli jeszcze nie istnieje.Ale wiesz co? Nie robi to pustych katalogów potomnych. Mógłbym dokonać przekierowania przez ten rurociąg, ale to tylko warunek wyścigu, który czeka na to, aby się wydarzyć. Najprostszy jest prawdopodobnie najlepszy. Po prostu zrób to później:
Lub, ponieważ Gilles ma bardzo dobry punkt w swojej odpowiedzi, aby zachować uprawnienia do katalogu, powinienem również spróbować. Myślę, że to zrobi:
Byłbym skłonny założyć się, że to szybciej niż
mkdir
tak.źródło
Oto szybka i brudna metoda
rsync
. W tym przykładzie uważam, że wszystko poniżej 10 MB jest „małe”.Najpierw przenieś tylko małe pliki:
rsync -a --max-size=10m srcdir dstdir
Następnie przenieś pozostałe pliki. Przeniesione wcześniej małe pliki nie zostaną ponownie skopiowane, chyba że zostaną zmodyfikowane.
rsync -a srcdir dstdir
Od
man 1 rsync
Oczywiście kolejność przesyłania plików po pliku nie jest ściśle od najmniejszej do największej, ale myślę, że może to być najprostsze rozwiązanie, które spełnia ducha Twoich wymagań.
źródło
--copy-dest=DIR
i / lub--compare-dest=DIR
myślę. Wiem tylko, bo musiałem dodać--hard-dereference
się dotar
po zaksięgowaniu własną odpowiedź, ponieważ brakowało mi linki. Wydaje mi się, że irsync
tak zachowuje się bardziej specyficznie dla lokalnych systemów plików z tymi innymi - użyłem go z kluczami USB i zalałoby to magistralę, chyba że ustawię limit przepustowości. Myślę, że powinienem był użyć jednego z tych innych.Nie
cp
bezpośrednio, to znacznie przekracza jego możliwości. Ale możesz ustawić wywoływaniecp
plików we właściwej kolejności.Zsh wygodnie umożliwia sortowanie plików według rozmiaru za pomocą kwalifikatora glob . Oto fragment kodu zsh, który kopiuje pliki w kolejności rosnącej od dolnej
/path/to/source-directory
do dolnej/path/to/destination-directory
.Zamiast pętli możesz użyć
zcp
funkcji. Najpierw jednak musisz utworzyć katalog docelowy, co można zrobić w tajemniczym oneliner.To nie chroni własności katalogów źródłowych. Jeśli chcesz, musisz zapisać odpowiedni program do kopiowania, taki jak
cpio
lubpax
. Jeśli to zrobisz, nie musisz dzwonićcp
anizcp
dodatkowo.źródło
Nie wydaje mi się, żeby można to
cp -r
zrobić bezpośrednio. Ponieważ może upłynąć nieokreślony czas, zanim pojawi się kreatorfind
/awk
rozwiązanie, oto krótki skrypt w perlu:Użyj tego:
./whatever.pl /src/path /dest/path
Argumenty powinny być ścieżkami bezwzględnymi ;
~
lub cokolwiek innego, co powłoka rozwija na ścieżkę absolutną, jest w porządku.Jeśli dodasz trzeci argument (cokolwiek, z wyjątkiem literału
0
), zamiast go skopiować, wydrukuje standardowy raport o tym, co by zrobił, z rozmiarami plików w bajtach, np.Zauważ, że są w porządku rosnącym według rozmiaru.
cp
Komenda na linii 34 jest poleceniem powłoki dosłowne, więc możesz robić, co chcesz z przełączników (tylko używane-a
, aby zachować wszystkie cechy).File::Find
iFile::Basename
oba są modułami podstawowymi, tzn. są dostępne we wszystkich instalacjach Perla.źródło
cp - copy smallest files first?
ale tytuł postu jest po prostu. Wcopy smallest files first?
każdym razie opcje nigdy nie zaszkodzą mojej filozofii, ale ty i David jesteście jedynymi, którzy skorzystali,cp
a ty jesteś jedynym, który to zrobił.cp
było to, że jest to najprostszy sposób na zachowanie właściwości pliku * nix w perlu (zorientowanym na wiele platform). Powodem, dla którego wyświetla się pasek przeglądarki,cp -
jest funkcja SE (niemądra), w wyniku której najpopularniejszy z wybranych tagów pojawia się przed rzeczywistym tytułem.pearl
jak wychodzi z tutejszej stolarki.inną opcją byłoby użycie cp z wyjściem du:
Można to nadal zrobić w jednym wierszu, ale podzieliłem go, abyś mógł go przeczytać
źródło