Yanıtlar:
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
Bir dosya tanımlayıcısını dosyaya açıp silerek, komut dosyaları çıktığında (öldürmeler ve çökmeler dahil) bir dosyanın silindiğinden emin olabilirsiniz. /proc/$PID/fd/$FD
Dosya tanıtıcısı açık olduğu sürece, dosya kullanılabilir durumda kalır (komut dosyası için; gerçekten diğer işlemler için değil , bir çalışma ortamıdır). Kapatıldığında (işlem başladığında çekirdeğin otomatik olarak yaptığı) dosya sistemi dosyayı siler.
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3
/proc
- sahip olmayan sistemler hariç.
exec 3> "$tmpfile"
? Bu yalnızca tmpfile tek başına bir komut dosyasıysa yararlı olmaz mı?
cat <&3
verecek Bad file descriptor
. Düzeltirseniz veya çıkarırsanız sevinirim; yanlış bilgilendirme pek yardımcı olmuyor.
mktemp
Geçici bir dosya veya dizin oluşturmak için kullanın :
temp_file=$(mktemp)
Veya bir şekerleme için:
temp_dir=$(mktemp -d)
Betiğin sonunda geçici dosyayı / dir silmeniz gerekir:
rm ${temp_file}
rm -R ${temp_dir}
mktemp, /tmp
dizinde veya --tmpdir
argümanla verilen dizgede dosya oluşturur .
trap "rm -f $temp_file" 0 2 3 15
Dosyayı oluşturduktan hemen sonra kullanabilirsiniz , böylece komut dosyası çıktıktan veya ctrl-C
dosya durdurulduktan sonra hala kaldırılır.
EXIT
Tek kanca ne için olur trap
?
kill -9 $somepid
. Bu özel öldürme sinyali, başka hiçbir şey olmadan, insta-ölümdür.
bash -c 'echo $$; trap "echo foo" 0; sleep 5'
EXIT
yeterli.
Eğer mktemp olan bir sistemde iseniz , diğer cevaplar olarak kullanmalısınız.
POSIX araç testi ile:
umask 0177
tmpfile=/tmp/"$0"."$$"."$(awk 'BEGIN {srand();printf "%d\n", rand() * 10^10}')"
trap 'rm -f -- "$tmpfile"' INT TERM HUP EXIT
: > "$tmpfile"
EXIT
Tek kanca olsaydı ne olur trap
?
tmpfile
komut dosyası çıkmadan önce hala kaldırılıyor, ancak komut dosyası başka sinyaller aldığında da kaldırılmıyor.
That's not what happens
?
mktemp
HP / UX'te farklı bir sözdizimine sahip kaynak. Todd C. Miller, 90'ların ortalarında OpenBSD için farklı bir tane yarattı (FreeBSD ve NetBSD tarafından kopyalandı) ve daha sonra bağımsız bir yardımcı program olarak da kullanılabilir hale getirdi (www.mktemp.org). Genellikle Linux'ta (çoğunlukla uyumlu) bir mktemp
yardımcı program 2007'de GNU coreutil'lerine ekleninceye kadar kullanılandır. Sadece birisinin gerçekten söyleyemediği mktemp
bir GNU yardımcı programı olduğunu söylemek mümkün değildir .
Bazı mermilerin yerleşik özelliği vardır.
zsh
'nin =(...)
işlem değiştirme şekli geçici bir dosya kullanıyor. Örneğin =(echo test)
, içeren geçici bir dosyanın yoluna genişler test\n
.
$ {cat $file; ls -l /dev/fd/3; echo test2 >&3; cat $file} 3<> ${file::==(echo test)}
test
lrwx------ 1 stephane stephane 64 Jan 30 11:19 /dev/fd/3 -> /tmp/zshMLbER0
test2
Komut tamamlandıktan sonra bu dosya otomatik olarak kaldırılır.
İşte dosyaları veya burada-dizeleri içinde bash
ve zsh
silinen geçici dosyalar olarak uygulanmaktadır.
Yani yaparsan:
exec 3<<< test
Dosya tanımlayıcısı 3, içeren silinmiş bir geçici dosyaya bağlanır test\n
.
İçeriğini şunlarla alabilirsiniz:
cat <&3
Linux'ta ise, bu dosyayı da okuyabilir veya yazabilirsiniz. /dev/fd/3
$ exec 3<<< test
$ cat <&3
test
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
(diğer bazı mermiler borular kullanmaktadır veya /dev/null
burada doc boşsa kullanabilirler).
mktemp
POSIX yardımcı programı yok . Ancak POSIX bir mkstemp(template)
C API belirtir ve m4
standart yardımcı program bu API'yi mkstemp()
m4 işleviyle aynı adla gösterir.
mkstemp()
Size işlev çağrıldığında var olmama garantisi verilen rastgele kısmı olan bir dosya adı verir. 0600 izinli dosyayı yarışsız bir şekilde oluşturur.
Yani yapabilirsin:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
Bununla birlikte, çıkış sırasında temizliği yapmanız gerektiğine dikkat edin, ancak dosyayı yalnızca birkaç kez yazıp okumanız gerekirse, dosyayı burada açabilir ve burada-doc / here- için oluşturduktan hemen sonra silebilirsiniz. Yukarıdaki dize yaklaşımı:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
# open once for writing, twice for reading:
exec 3> "$tempfile" 4< "$tempfile" 5< "$tempfile"
rm -f -- "$tmpfile"
cmd >&3 # store something in the temp file
exec 3>&- # fd no longer needed
# read the content twice:
cat <&4
cat <&5
Dosyayı bir kez okumak için açabilir ve iki okuma arasında geri sarabilirsiniz, ancak bu geri sarma işlemini yapabilen bir POSIX yardımcı programı yoktur lseek()
, bu nedenle bir POSIX komut dosyasında ( zsh
( sysseek
yerleşik) ve ksh93
( <#((...))
işleç) yapabilirsiniz. olsa yap).
<()
=(...)
.
İşte Hauke Laging'in çizgisinde biraz daha gelişmiş bir cevap:
#!/bin/bash
tmpfile=$(mktemp) # Create a temporal file in the default temporal folder of the system
# Lets do some magic for the tmpfile to be removed when this script ends, even if it crashes
exec {FD_W}>"$tmpfile" # Create file descriptor for writing, using first number available
exec {FD_R}<"$tmpfile" # Create file descriptor for reading, using first number available
rm "$tmpfile" # Delete the file, but file descriptors keep available for this script
# Now it is possible to work with the temporal file
echo foo >&$FD_W
echo bar >&$FD_W # Note that file descriptor always concatenates, not overwrites
cat <&$FD_R
Genellikle geçici dosyalar içeren iş akışım, test ettiğim bash betiğinden kaynaklanıyor. Bunu yapmak istiyorum, tee
böylece çalıştığını görebiliyorum ve işlemimin bir sonraki yinelemesi için çıktıyı korudum. Adlı bir dosya oluşturdumtmp
#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))
böylece onu kullanabilirim
$ some_command --with --lots --of --stuff | tee $(tmp)
Datetime'nın rastgele değerlerden önce biçimlendirilmesinden hoşlanmamın nedeni, kolayca yaptığım tmp dosyasını bulmama izin veriyor ve bir dahaki sefere neye isim vereceğimi düşünmek zorunda değilim (ve sadece dang betiğimi almaya odaklanıyorum) çalışmak).