Poprawka lub alternatywa dla mktemp w OS X


72

Patrzę na skrypt bash, który napisał ktoś inny, który używa mktemp:

TEMP=`mktemp --directory`

Jednak ta linia nie działa na moim komputerze (OS X 10.6).

Jak mam naprawić tę linię, aby była kompatybilna z wieloma platformami typu X? EDYCJA: Alternatywne polecenie byłoby również wystarczające.

Odpowiedzi:


108

Oto, co ostatecznie wykorzystałem do niezawodnego utworzenia katalogu tymczasowego, który działa zarówno w systemie Linux, jak i Darwin (wszystkie wersje wcześniejsze niż Mac OS X 10.11), bez kodowania $TMPDIRlub /tmp:

mytmpdir=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`

Tło:

Komenda GNU mktemp nie wymaga żadnych argumentów. Zwykły mktempbędzie działać i utworzy plik tymczasowy w katalogu tymczasowym systemu.

Plain mktemp -dutworzy katalog zamiast pliku, którego chciałbyś użyć w systemie Linux.

(gnu-coreutils)$ man mktemp
> ..
> If DIR is not specified, uses $TMPDIR if set, else /tmp.
> ..

Domyślnie GNU mktemp używa szablonu tmp.XXXXXXXXXXdla nazwy podkatalogu (lub pliku). Aby dostosować ten szablon, -tmożna użyć tej opcji.

Mktemp OSX nie ma domyślnego szablonu i wymaga określenia szablonu. Niestety, gdy GNU mktemp bierze szablon jako -topcję, w OSX jest to przekazywane jako argument pozycyjny. Zamiast tego mktemp OSX ma -topcję, która oznacza coś innego. -tOpcja na OSX jest udokumentowane jako „prefix” dla szablonu. Jest rozwinięty do {prefix}.XXXXXXXX, więc dodaje do niego Xs automatycznie (np. mktemp -d -t exampleMoże utworzyć example.zEJZWCTQw katalogu temp).

Byłem zaskoczony, że w wielu środowiskach Linux, $TMPDIRjest nie ustawiona domyślnie. Wiele programów CLI obsługuje to ustawienie, ale nadal wymaga ustawień domyślnych /tmp. Oznacza to, że przekazywanie $TMPDIR/example.XXXXXXXXdo mktemp lub mkdir jest niebezpieczne, ponieważ może tworzyć /example.XXXXXXXXw katalogu głównym dysku lokalnego (ponieważ $ TMPDIR jest rozbrojony i staje się pustym ciągiem).

W OSX $TMPDIRzawsze jest ustawiony i (przynajmniej w domyślnej powłoce) nie jest ustawiony na /tmp(co jest dowiązaniem symbolicznym /private/tmp), ale na /var/folders/dx/*****_*************/T. Cokolwiek więc robimy dla OSX, powinno szanować to domyślne zachowanie.

Podsumowując, oto co skończyło się używając do niezawodnie utworzyć katalog tymczasowy, który działa zarówno na Linux i Darwin (Mac OS X), bez sztywno albo $TMPDIRalbo /tmp:

mytmpdir=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`

Pierwsza część dotyczy Linuksa. To polecenie zakończy się niepowodzeniem w systemie Darwin (Mac OS X) z kodem błędu 1odpowiadającym słowem „wykorzystanie: ...”. Dlatego ignorujemy stderr i zamiast tego uruchamiamy wariant Mac. mytmpdirPrefiks jest używany tylko na Mac (gdzie wymagana jest opcja, że należy ustawić).


12
Bardzo fajny. Czasami różne zachowanie OS X jest denerwujące.
therealmarv

6
@therealmarv Wolę powiedzieć, zawsze.
Nikita Volkov

10
Właśnie uruchomiłem mktemp -dna OS X 10.11.5 El Capitan i działało to zgodnie z oczekiwaniami file $(mktemp -d):: /var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory
Heath Borders

2
Tak. Byłem zaskoczony, ponieważ byłeś tym Just Worked ™.
Heath Borders

1
Również, jeśli chcesz uruchomić mktemp -d -t 'mytmpdir'w systemie Linux (testowane mktempz coreutils 8.26), to działa zgodnie z oczekiwaniami.

15

Musisz dostarczyć szablon. mktemp -d /tmp/foo.XXXXpowinno działać. Nigdy nie widziałam --directory. --Sugeruje, że jest to rozszerzenie GNU.


6
Jeśli chcesz użyć, $TMPDIRgdy jest dostępny, zrób mktemp -d "${TMPDIR:-/tmp}"/foo.XXXX. Działa to w wersji bash na Macu i dash na Debianie, więc wydaje się przenośne.
Tom Anderson

9

Zmień --directoryna -d. Pierwszy z nich to GNU-ism, ale GNU mktempz coreutils również obsługuje -d. W mktempOS X jest taki sam jak w BSD, więc -dpowinien być dość przenośny wśród systemów, które faktycznie wysyłają mktempprogram.


Właśnie próbowałem mktemp -di to też nie działa.
mindeavour.

1
Kyle ma pełną odpowiedź. System mktempoperacyjny OS X wymaga szablonu. Skrypt, którego używasz, zakłada konwencje GNU, które używają domyślnego szablonu, jeśli żaden nie jest dostarczony.
James Sneeringer

Problem polega na tym, że Unix oczekuje, XXXXXże zostanie dostarczony w szablonie, ponieważ ponieważ OS X nie ma pewności, czy istnieje zgodna flaga szablonu?
user3467349,

2
mktempna OS X 10.11.5 El Capitan działa dla mnie file $(mktemp -d)::/var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory
Heath Borders

4
temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX")"
  • mktempdla BSD (w tym OSX ) wymaga szablonu, ale pozwala na dowolną liczbę Xs w szablonie.
  • (GNU) mktempdla systemu Linux nie wymaga szablonu, jednak jeśli szablon jest określony, liczba Xs musi wynosić 6.

Zauważ, że -tjest nieaktualny dla GNUmktemp , więc byłby to kod bardziej przyszłościowy

temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX" 2>/dev/null || mktemp -q -d)"
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.