@Felix: Zastanawiałem się nad tym samym. Cofnąłem się do pierwszej wersji, ale tak się stało "old_location/*.*. Nie mogę znaleźć wersji zawierającej "old_location/.".
Asaph
@Asaph: Twoje wycofanie było w porządku, spójrz na historię ... Miałem na myślicopy ("old_location/.","new_location/");
@ Oliboy50: Możesz zapytać osobę, która napisała kod 5 lat temu: php.net/manual/en/function.copy.php#91010 . Może wtedy bardziej popularne było tłumienie komunikatów o błędach.
Świetnie się spisało, aby skopiować folder ze 140 podfolderami i każdym podfolderem zawierającym 21 obrazów. Działa świetnie! Dzięki!
Darksaint2014
1
mkdirpowinien zostać dodany truejako ostatni parametr do obsługi katalogu rekurencyjnego, wtedy ten skrypt jest doskonały
ZenithS
Spowoduje to skopiowanie całego folderu? A co, jeśli chcesz skopiować tylko pliki wewnątrz folderu, bez folderu nadrzędnego, zgodnie z pytaniem: copy ("old_location/*.*","new_location/");Czy to działa? A jeśli masz pliki z kropkami, czy zostaną dopasowane?
XCS
35
copy () działa tylko z plikami.
Zarówno polecenia copy systemu DOS, jak i polecenia cp w systemie Unix będą kopiować rekursywnie - więc najszybszym rozwiązaniem jest po prostu ich wyrzucenie i użycie. na przykład
`cp -r $src $dest`;
W przeciwnym razie będziesz musiał użyć opendir/ readdirlub scandirdo odczytania zawartości katalogu, iteracji w wynikach i jeśli is_dir zwróci true dla każdego z nich, powtórz w nim.
Oto bardziej stabilna i czystsza wersja xcopy (), która nie tworzy folderu, jeśli istnieje: function xcopy($src, $dest) { foreach (scandir($src) as $file) { $srcfile = rtrim($src, '/') .'/'. $file; $destfile = rtrim($dest, '/') .'/'. $file; if (!is_readable($srcfile)) { continue; } if ($file != '.' && $file != '..') { if (is_dir($srcfile)) { if (!file_exists($destfile)) { mkdir($destfile); } xcopy($srcfile, $destfile); } else { copy($srcfile, $destfile); } } } }
TheStoryCoder
Dzięki za rozwiązanie backtick ! Strona, która pomogła mi ulepszyć polecenie kopiowania: wyjaśniono UNIX cp . Dodatkowe informacje: PHP> = 5.3 oferuje kilka fajnych iteratorów
Nie będzie działać na serwerach Windows ani w innych środowiskach, w których nie masz dostępu do shell_execlub cp. To sprawia, że - moim zdaniem - nie jest to „najlepsze” rozwiązanie.
The Pellmeister
3
Poza tym sterowanie wierszem poleceń z pliku PHP może być dużym problemem, gdy ktoś znajdzie sposób na pobranie pliku na serwer.
Martijn,
Działał jak urok! Na CentOS i działało świetnie. Dzięki @bstpierre
Nick Green
1
To w ogóle nie zadziała w systemie Windows, ponieważ cpjest to polecenie systemu Linux. Do użytku w systemie Windows xcopy dir1 dir2 /e /i, gdzie /eoznacza kopiowanie pustych katalogów i /iignorowanie pytań dotyczących plików lub katalogów
Michel
Tak, jest to najlepsze rozwiązanie, jeśli Twój serwer obsługuje to polecenie i masz wymagane uprawnienia. To jest bardzo szybkie. Niestety nie działa we wszystkich środowiskach.
Jak wspomniano w innym miejscu, copydziała tylko z jednym plikiem źródłowym, a nie wzorcem. Jeśli chcesz kopiować według wzorca, użyj globdo określenia plików, a następnie uruchom kopiowanie. Nie spowoduje to jednak skopiowania podkatalogów ani utworzenia katalogu docelowego.
function copyToDir($pattern, $dir){foreach(glob($pattern)as $file){if(!is_dir($file)&& is_readable($file)){
$dest = realpath($dir . DIRECTORY_SEPARATOR). basename($file);
copy($file, $dest);}}}
copyToDir('./test/foo/*.txt','./test/bar');// copies all txt files
Pełne podziękowania należą się Felixowi Klingowi za doskonałą odpowiedź, której z wdzięcznością użyłem w moim kodzie. Oferuję niewielkie rozszerzenie wartości logicznej zwracanej w celu zgłaszania sukcesu lub niepowodzenia:
używasz recurse_copy () i recurseCopy () jako nazw funkcji, zaktualizuj je.
AgelessEssence
The closedir ($ dir); instrukcja musi znajdować się poza instrukcją if ($ reslut === true), tj. o jeden nawias klamrowy dalej. W przeciwnym razie ryzykujesz posiadaniem niezwolnionych zasobów.
Dimitar Darazhanski
7
Dzięki Symfony jest to bardzo łatwe do osiągnięcia:
Moja przycięta wersja odpowiedzi @Kzoty. Dziękuję Kzoty.
Stosowanie
Helper::copy($sourcePath, $targetPath);classHelper{staticfunction copy($source, $target){if(!is_dir($source)){//it is a file, do a normal copy
copy($source, $target);return;}//it is a folder, copy its files & sub-folders@mkdir($target);
$d = dir($source);
$navFolders = array('.','..');while(false!==($fileEntry=$d->read())){//copy one by one//skip if it is navigation folder . or ..if(in_array($fileEntry, $navFolders)){continue;}//do copy
$s ="$source/$fileEntry";
$t ="$target/$fileEntry";self::copy($s, $t);}
$d->close();}}
Miałem podobną sytuację, w której musiałem kopiować z jednej domeny do drugiej na tym samym serwerze.Oto dokładnie to, co zadziałało w moim przypadku, możesz również dostosować do swojej:
Zwróć uwagę na użycie „substr ()”, bez niej miejscem docelowym staje się „/home/user/abcde.com/../folder/”, co może być czymś, czego nie chcesz. Dlatego użyłem funkcji substr (), aby wyeliminować pierwsze 3 znaki (../), aby uzyskać żądane miejsce docelowe, którym jest „/home/user/abcde.com/folder/”. Możesz więc dostosować funkcję substr (), a także funkcję glob (), aż będzie pasować do twoich osobistych potrzeb. Mam nadzieję że to pomoże.
"old_location/."
była tylko literówka?"old_location/*.*
. Nie mogę znaleźć wersji zawierającej"old_location/."
.copy ("old_location/.","new_location/");
Odpowiedzi:
Wygląda na to, że kopia obsługuje tylko pojedyncze pliki . Oto funkcja rekurencyjnego kopiowania, którą znalazłem w tej uwadze na stronie dokumentacji kopiowania :
źródło
@mkdir
zamiastmkdir
?Jak opisano tutaj , jest to kolejne podejście, które zajmuje się również linkami symbolicznymi:
źródło
mkdir
powinien zostać dodanytrue
jako ostatni parametr do obsługi katalogu rekurencyjnego, wtedy ten skrypt jest doskonałycopy ("old_location/*.*","new_location/");
Czy to działa? A jeśli masz pliki z kropkami, czy zostaną dopasowane?copy () działa tylko z plikami.
Zarówno polecenia copy systemu DOS, jak i polecenia cp w systemie Unix będą kopiować rekursywnie - więc najszybszym rozwiązaniem jest po prostu ich wyrzucenie i użycie. na przykład
W przeciwnym razie będziesz musiał użyć
opendir
/readdir
lubscandir
do odczytania zawartości katalogu, iteracji w wynikach i jeśli is_dir zwróci true dla każdego z nich, powtórz w nim.na przykład
źródło
function xcopy($src, $dest) { foreach (scandir($src) as $file) { $srcfile = rtrim($src, '/') .'/'. $file; $destfile = rtrim($dest, '/') .'/'. $file; if (!is_readable($srcfile)) { continue; } if ($file != '.' && $file != '..') { if (is_dir($srcfile)) { if (!file_exists($destfile)) { mkdir($destfile); } xcopy($srcfile, $destfile); } else { copy($srcfile, $destfile); } } } }
Najlepszym rozwiązaniem jest!
źródło
shell_exec
lubcp
. To sprawia, że - moim zdaniem - nie jest to „najlepsze” rozwiązanie.cp
jest to polecenie systemu Linux. Do użytku w systemie Windowsxcopy dir1 dir2 /e /i
, gdzie/e
oznacza kopiowanie pustych katalogów i/i
ignorowanie pytań dotyczących plików lub katalogówźródło
Jak wspomniano w innym miejscu,
copy
działa tylko z jednym plikiem źródłowym, a nie wzorcem. Jeśli chcesz kopiować według wzorca, użyjglob
do określenia plików, a następnie uruchom kopiowanie. Nie spowoduje to jednak skopiowania podkatalogów ani utworzenia katalogu docelowego.źródło
z ostatniej czwartej linii, zrób to
i
źródło
Pełne podziękowania należą się Felixowi Klingowi za doskonałą odpowiedź, której z wdzięcznością użyłem w moim kodzie. Oferuję niewielkie rozszerzenie wartości logicznej zwracanej w celu zgłaszania sukcesu lub niepowodzenia:
źródło
Dzięki Symfony jest to bardzo łatwe do osiągnięcia:
Zobacz https://symfony.com/doc/current/components/filesystem.html
źródło
Moja przycięta wersja odpowiedzi @Kzoty. Dziękuję Kzoty.
Stosowanie
źródło
Klonuję cały katalog przez Iterator katalogu SPL.
źródło
źródło
W przypadku serwerów Linux potrzebujesz tylko jednej linii kodu do rekurencyjnego kopiowania z zachowaniem uprawnień:
Innym sposobem na to jest:
ale jest wolniejszy i nie zachowuje uprawnień.
źródło
Miałem podobną sytuację, w której musiałem kopiować z jednej domeny do drugiej na tym samym serwerze.Oto dokładnie to, co zadziałało w moim przypadku, możesz również dostosować do swojej:
Zwróć uwagę na użycie „substr ()”, bez niej miejscem docelowym staje się „/home/user/abcde.com/../folder/”, co może być czymś, czego nie chcesz. Dlatego użyłem funkcji substr (), aby wyeliminować pierwsze 3 znaki (../), aby uzyskać żądane miejsce docelowe, którym jest „/home/user/abcde.com/folder/”. Możesz więc dostosować funkcję substr (), a także funkcję glob (), aż będzie pasować do twoich osobistych potrzeb. Mam nadzieję że to pomoże.
źródło