Jak kopiować tylko pasujące pliki, zachowując podkatalogi

6

Czy można to zrobić: „Jak mogę skopiować podzbiór plików z katalogu, zachowując jednocześnie strukturę folderów?” , ale bez użycia rsync?

Czy można to zrobić tylko przy użyciu cp, find i grep?

Mam bardzo ograniczoną powłokę bash (tj. Jest to powłoka git pod Windows :(), więc rsync nie jest opcją.

Wiem, że mogę dostać cygwin, ale zastanawiałem się, co mogę zrobić w tej ograniczonej sytuacji.

Słoneczny
źródło
Czy byłeś bashdostępny?
enzotib,
OT: robocopymożna to zrobić bezpośrednio w systemie Windows ( robocopy /S sourcedir targetdir *blah*)
Mat
lub wget dla systemu Windows
bsd
@enzotib: tak, wygląda na to, że jest bardzo ograniczony.
Sunny

Odpowiedzi:

8

Możesz użyć tarlub cpiolub pax(jeśli którykolwiek z nich jest dostępny), aby skopiować określone pliki, tworząc w razie potrzeby katalogi docelowe. Za pomocą GNU tar, aby skopiować wszystkie zwykłe pliki o nazwie *.txtlub README.*pod bieżącym katalogiem do tej samej hierarchii pod ../destination:

find . -type f \( -name '*.txt' -o -name 'README.*' \) |
tar -cf - -T - |
tar -xf - -C ../destination

Wystarczy find, cp, mkdira powłoki, można pętli nad pożądanych plików z findi uruchomić polecenie powłoki kopiować każdego z nich. Jest to powolne i uciążliwe, ale bardzo przenośne. Fragment powłoki otrzymuje docelowy katalog główny as $0i ścieżkę do pliku źródłowego as $1; w razie potrzeby tworzy docelowe drzewo katalogów (zwróć uwagę, że uprawnienia do katalogu nie są zachowywane przez poniższy kod), a następnie kopiuje plik. Poniższy fragment kodu działa w każdym systemie POSIX i większości instalacji BusyBox.

find . -type f \( -name '*.txt' -o -name 'README.*' \) -exec sh -c '
  mkdir -p "$0/${1%/*}";
  cp -p "$1" "$0/$1"
' ../destination {} \;

Możesz grupować shwywołania; jest to trochę skomplikowane, ale może być mierzalnie szybsze.

find . -type f \( -name '*.txt' -o -name 'README.*' \) -exec sh -c '
  for x; do
    mkdir -p "$0/${x%/*}";
    cp -p "$x" "$0/$x";
  done
' ../destination {} +

Jeśli masz bash ≥4 (nie wiem, czy Git Bash jest wystarczająco nowy), nie musisz dzwonić find, możesz użyć **wzorca globu, aby powrócić do podkatalogów.

shopt -s globstar extglob
for x in **/@(*.txt|README.*); do
  mkdir -p "../destination/${x%/*}"
  cp -p -- "$x" "../destination/$x"
done
Gilles
źródło
1

Możesz spróbować czegoś takiego:

ls | grep 2 | xargs -n1 -t -i cp -R {} ../testdirTwo/{}

Próbowałem tego na moim systemie Linux i działa. Zwróć uwagę na parametr -R w cp, jeśli chcesz, to rekurencyjny. Zwróć także uwagę na parametr -i o xargs, wstawi on dane wyjściowe do miejsca, w którym umieścisz {}. -t służy tylko do powtórzenia polecenia stderr.

Moja struktura katalogu testowego wyglądała następująco:

$ find .
.
./2
./2/f2
./1
./1/f1
./f1
./f2
Patkos Csaba
źródło