Jeśli masz ścieżkę do pliku (na przykład /home/bob/test/foo.txt), gdzie każdy podkatalog na ścieżce może lub nie może istnieć, w jaki sposób mogę utworzyć plik foo.txt w taki sposób, aby używa "/home/bob/test/foo.txt" jako jedynego wejścia zamiast tworzyć każdy nieistniejący katalog w ścieżce jeden po drugim i ostatecznie tworzyć sam plik foo.txt?Jak mogę utworzyć ścieżkę ze wszystkimi jej podkatalogami za jednym razem w Perlu?
Odpowiedz
Można użyć File::Basename i File::Path
use strict;
use File::Basename;
use File::Path qw/make_path/;
my $file = "/home/bob/test/foo.txt";
my $dir = dirname($file);
make_path($dir);
open my $fh, '>', $file or die "Ouch: $!\n"; # now go do stuff w/file
I nie dodawać żadnych testów w celu sprawdzenia, czy plik już istnieje, ale to dość łatwo dodać z Perl.
Zastosowanie make_dir from File::Util
use File::Util;
my($f) = File::Util->new();
$f->make_dir('/var/tmp/tempfiles/foo/bar/');
# optionally specify a creation bitmask to be used in directory creations
$f->make_dir('/var/tmp/tempfiles/foo/bar/',0755);
Nie sądzę, istnieje standardowa funkcja, która może zrobić wszystko, o co prosisz, bezpośrednio z pliku.
Ale mkpath(), z modułu File :: Path, może prawie to zrobić, podając katalog nazwy pliku. Od docs File :: Ścieżka:
Funkcja „mkpath” zapewnia wygodny sposób tworzyć katalogi, nawet jeśli „mkdir” wywołanie jądro nie utworzy więcej niż jeden poziom w katalogu czas.
Zauważ, że mkpath() nie zgłasza błędów w miły sposób: z jakiegoś powodu umiera zamiast tylko zwracać zero.
Biorąc pod uwagę to wszystko, można zrobić coś takiego:
use File::Basename;
use File::Path;
my $fname = "/home/bob/test/foo.txt";
eval {
local $SIG{'__DIE__'}; # ignore user-defined die handlers
mkpath(dirname($fname));
};
my $fh;
if ([email protected]) {
print STDERR "Error creating dir: [email protected]";
} elsif (!open($fh, ">", $fname)) {
print STDERR "Error creating file: $!\n";
}
Podstawowy kod ma około dwóch dekad, a od tego czasu mody programistyczne bardzo się zmieniły. Korzystasz ze starego stylu File :: Path interface. Nowy interfejs umożliwia wychwycenie wszystkich błędów i radzenie sobie z nimi (lub ignorowanie ich) w zależności od potrzeb. – dland
Dobrze wiedzieć, że istnieje nowy interfejs. Jestem przyzwyczajony do pisania przenośnego Perla, który działa na stare wersje i na różne systemy operacyjne (stąd, na dwóch argach open()), więc zwykle nie dokuczam sobie, ucząc się, co nowego w Perlu. :-) –
@Michael: Rozumiem, że być może będziesz musiał napisać stary Perl z jakichkolwiek powodów, ale nie rozumiem, dlaczego wysłałeś taki kod jako przykład dla innych. Jeśli wiesz o trzyargumentowej formie 'otwartej', użyj go tutaj. Nie potrzebujemy więcej przykładów w sieci dwuargumentowej; mamy już wystarczająco dużo. – Telemachus
Chyba masz na myśli, a nie '' mkpath' make_path'? W przeciwnym razie dobra odpowiedź. – hobbs
@Hobbs: sprawdź dokumentację dla 'File :: Path'. 'mkpath' jest opisany jako" starsza wersja ", a nowy interfejs używa' make_path' dla tej funkcji. – Telemachus
Ah, to ostatnia zmiana. Wersja, którą mam, nie ma tego interfejsu. :) – hobbs