Saya memiliki skenario yang meminta penggantian perintah tanpa menggunakan subshell. Saya memiliki konstruk seperti ini:
pushd $(mktemp -d)
Sekarang saya ingin keluar dan menghapus direktori sementara dalam sekali jalan:
rmdir $(popd)
Namun itu tidak berhasil karena popd
tidak mengembalikan direktori muncul (itu mengembalikan direktori baru, sekarang saat ini) dan juga karena dilakukan dalam subkulit.
Sesuatu seperti
dirs -l -1 ; popd &> /dev/null
akan mengembalikan direktori yang muncul tetapi tidak dapat digunakan seperti ini:
rmdir $(dirs -l -1 ; popd &> /dev/null)
karena popd
hanya akan mempengaruhi subkulit. Yang dibutuhkan adalah kemampuan untuk melakukan ini:
rmdir { dirs -l -1 ; popd &> /dev/null; }
tapi itu sintaks yang tidak valid. Apakah mungkin untuk mencapai efek ini?
(catatan: Saya tahu saya bisa menyimpan direktori sementara dalam sebuah variabel; Saya berusaha menghindari keharusan untuk melakukannya dan mempelajari sesuatu yang baru dalam proses!)
trap
pawang dapat membersihkan direktori jika prosesnya ditusuk oleh sinyal.fish
, setara dengan substitusi perintah()
,, mengubah folder shell luar. Ini biasanya menjengkelkan, tetapi dalam kasus seperti ini itu berguna, saya yakin.Jawaban:
Pilihan judul pertanyaan Anda agak membingungkan.
pushd
/popd
,csh
fitur yang disalin olehbash
danzsh
, adalah cara untuk mengelola tumpukan direktori yang diingat.mendorong direktori kerja saat ini ke tumpukan, dan kemudian mengubah direktori kerja saat ini (dan kemudian mencetak
/some/dir
diikuti oleh konten tumpukan itu (dipisahkan ruang).mencetak isi tumpukan (sekali lagi, dipisahkan dengan ruang) dan kemudian berubah ke elemen atas tumpukan dan mengeluarkannya dari tumpukan.
(juga berhati-hatilah bahwa beberapa direktori akan diwakili sana dengan mereka
~/x
atau~user/x
notasi).Jadi jika tumpukan saat ini memiliki
/a
dan/b
, direktori saat ini adalah/here
dan Anda sedang menjalankan:pushd
akan mencetak/tmp/whatever /here /a /b
danpopd
akan menampilkan/here /a /b
, bukan/tmp/whatever
. Itu independen menggunakan substitusi perintah atau tidak.popd
tidak dapat digunakan untuk mendapatkan path dari direktori sebelumnya, dan secara umum outputnya tidak dapat diproses pasca (lihat array$dirstack
atau$DIRSTACK
beberapa shell meskipun untuk mengakses elemen-elemen dari stack direktori)Mungkin Anda ingin:
Atau
Padahal, saya akan menggunakan:
Bagaimanapun,
pushd "$(mktemp -d)"
tidak berjalanpushd
dalam subkulit. Jika ya, itu tidak bisa mengubah direktori kerja. Itumktemp
yang berjalan dalam subkulit. Karena itu adalah perintah yang terpisah, itu harus dijalankan dalam proses yang terpisah. Itu menulis outputnya pada pipa, dan proses shell membacanya di ujung pipa yang lain.ksh93 dapat menghindari proses terpisah ketika perintah dibangun di dalam, tetapi bahkan di sana, itu masih sebuah subkulit (lingkungan kerja yang berbeda) yang kali ini ditiru daripada mengandalkan pada lingkungan terpisah yang biasanya disediakan oleh forking. Misalnya, dalam
ksh93
,,a=0; echo "$(a=1; echo test)"; echo "$a"
tidak ada percabangan yang terlibat, tetapi masihecho "$a"
menghasilkan0
.Di sini, jika Anda ingin menyimpan output
mktemp
dalam variabel, pada saat yang sama ketika Anda meneruskannya kepushd
, denganzsh
, Anda bisa melakukan:Dengan kerang mirip Bourne lainnya:
Atau untuk menggunakan output
$(mktemp -d)
beberapa kali tanpa secara eksplisit menyimpannya dalam variabel, Anda bisa menggunakanzsh
fungsi anonim:sumber
pushd
danpopd
bekerja seperti yang Anda jelaskan dan bahwa mereka independen dari penggantian komando - tidak ada kebingungan di sana! Namun, Anda menjawab dengan masalah sendiri dengan mengungkapkan$OLDPWD
. Saya bisa melakukannyapopd; rmdir $OLDPWD
. Itulah jawaban untuk masalah saya - semua yang lain hanya menegaskan apa yang saya pikirkan. Substitusi perintah tampaknya merupakan cara untuk menyelesaikannya tetapi bukan karena subkulit dan Anda tidak dapat melakukan substitusi perintah tanpa subkulit, Jadi terima kasih karena mengungkapkan OLDPWD - itulah yang saya butuhkan!rmdir $(popd)
menyebabkanpopd
dijalankan dalam sub-shell yang berarti tidak akan mengubah direktori saat ini, tetapi bahkan jika itu tidak berjalan dalam subkulit, outputpopd
tidak akan menjadi direktori sementara, itu akan menjadi daftar yang dipisahkan oleh ruang direktori tidak termasuk direktori temp. Di situlah saya mengatakan Anda bingung.OLDPWD
. Saya harus ingat suatu hari membacaman bash
dari ujung ke ujung!Anda dapat memutuskan tautan direktori terlebih dahulu, sebelum meninggalkannya:
atau
tetapi perhatikan bahwa
pushd
danpopd
benar-benar alat untuk shell interaktif, bukan untuk skrip (itulah sebabnya mereka sangat cerewet; perintah scripting sungguhan akan diam saat berhasil).sumber
Di bash,
dirs
berikan daftar direktori yang diingat dengan metode pushd / popd.Juga,
dirs -1
cetak direktori terakhir yang termasuk dalam daftar.Jadi, untuk menghapus direktori yang dibuat sebelumnya dengan mengeksekusi
pushd $(mktmp -d)
, gunakan:Dan kemudian,
popd
direktori yang sudah dihapus dari daftar:Semua dalam satu baris:
Dan menambahkan opsi (-l) untuk menghindari
~/x
atau~user/x
notasi:Yang sangat mirip dengan garis yang Anda minta.
Kecuali bahwa saya tidak akan menggunakan
&>
karena akan menyembunyikan pelaporan kesalahan olehpopd
.Catatan: Direktori akan tetap setelah
rmdir
karena padapwd
saat itu. Dan akan benar-benar dibatalkan tautannya setelahpopd
perintah (tidak ada tautan yang tersisa digunakan).Ada opsi untuk digunakan, untuk shell yang mendukung variabel "OLDPWD" (kebanyakan shell seperti bourne: ksh, bash, zsh miliki
$OLDPWD
). Sangat menarik untuk dicatat bahwa ksh tidak mengimplementasikan dirs, pod, pushd secara default (lksh, dash dan lainnya juga tidak memiliki popd yang tersedia, jadi, tidak dapat digunakan di sini):Atau, lebih idiomatis (daftar kerang yang sama seperti di atas):
sumber
rmdir
direktori saat ini di mana Anda akan berada ketika melakukan ini. Anda perlupopd
melakukan sebelum melakukanrmdir
tetapi Anda harus tahu apa yang harus dihapus danpopd
tidak memberi tahu Anda. Saya, seperti Anda, pikirdirs -l -1
adalah jawabannya tetapi sejak itu menemukan bahwa jawabannya sebenarnya untuk digunakan$OLDPWD
.popd && rmdir ~-
.rmdir "$PWD"
benar. Juga, direktori saat ini harus menjadi direktori yang dibuat olehmktmp -d
(jikapushd $(mktemp -d)
dieksekusi sebelumnya) dan yangpushd
memindahkan pwd. Jadi, ya, setelahpushd
dan sebelum popd, direktori yang dibuat disimpan$(dirs -1)
, saya gagal melihat masalah.