Bash có thể cung cấp unexpected results if one edits a script while the script is running. Nhưng thường rất thuận tiện để có thể chỉnh sửa bản sao tạm thời của tập lệnh mà tôi chạy trong một trình bao, nhưng hãy đảm bảo rằng nó đã trở lại vị trí ban đầu trước khi tôi chạy lại. Có ai có đề xuất cho một công việc hoặc các tùy chỉnh để Emacs để tạo điều kiện này?Quy trình làm việc của Emacs để chỉnh sửa tập lệnh Bash trong khi chúng chạy
Trả lời
M-x delete-file
, nhấn down
để chèn được đường dẫn đến tập tin bạn đang chỉnh sửa, và RET
để xóa các tập tin. Khi bạn tiếp tục lưu bộ đệm của bạn, điều này sẽ tạo ra một tập tin mới. Bash sẽ tiếp tục thực thi tệp cũ, đã bị xóa.
Nhân tiện, trong hầu hết các trường hợp, bạn thậm chí không cần thực hiện biện pháp phòng ngừa này. Emacs thường lưu vào một tệp tạm thời, sau đó đổi tên tệp tạm thời đó thành tên tệp thích hợp (xóa tệp cũ, trừ khi nó được giữ như một bản sao lưu). Emacs chỉ ghi đè lên tập tin tại chỗ nếu nó phát hiện ra rằng nó không thể tái tạo các tập tin đúng: nếu tập tin có liên kết cứng, hoặc nếu bạn không có quyền ghi vào thư mục. (Tôi đơn giản hóa một chút, các chi tiết nằm trong hàm basic-save-buffer-2
trong files.el
.) Miễn là tệp có một mục nhập thư mục duy nhất và bạn có quyền ghi vào thư mục chứa tập lệnh, chỉ cần bấm C-x C-s
.
tôi đã có chức năng đổi tên tệp bộ đệm hiện tại. là một bước nhảy ngắn đối với một chức năng giúp dễ dàng chuyển sang phiên bản tạm thời của một tệp và sau đó quay lại. về cơ bản, nếu bạn chạy hàm này khi truy cập một tệp thông thường "foo.txt", nó sẽ sao chép tệp vào một tệp mới trong cùng một thư mục có tên "tmp.foo.txt". chỉnh sửa như mong muốn. khi đã sẵn sàng để chuyển trở lại, hãy chạy lại hàm và nó sẽ di chuyển tệp tạm thời trở lại trên tệp gốc. tôi đã sử dụng tiền tố "tmp." thay vì hậu tố bởi vì hầu hết nhận dạng chế độ trong các emacs đều dựa trên hậu tố (bạn có thể làm điều gì đó huyền ảo hơn với việc nhớ tất cả các chế độ đệm và áp dụng lại ...).
(defun toggle-temp-file()
(interactive)
(let* ((cur-buf (current-buffer))
(cur-file (buffer-file-name cur-buf))
(cur-file-dir (file-name-directory cur-file))
(cur-file-name (file-name-nondirectory cur-file))
new-file)
(if (string-match "^tmp\\.\\(.+\\)\\'" cur-file-name)
;; temp file -> orig file
(progn
(setq new-file
(concat cur-file-dir (match-string 1 cur-file-name)))
(rename-file cur-file new-file t))
;; orig file -> temp file
(setq new-file (concat cur-file-dir "tmp." cur-file-name))
(copy-file cur-file new-file nil nil t))
(kill-buffer cur-buf)
(find-file new-file)))
Trong thư trả lời này, tôi
- bổ sung câu trả lời thoải mái bởi Gilles với lý thuyết.
- đề xuất một sự cải thiện trong việc sử dụng biểu tượng cảm xúc.
- đề xuất các lựa chọn thay thế, hoàn toàn bằng cách viết kịch bản lệnh shell.
Cảnh báo: Tôi không phải là lập trình viên chuyên nghiệp.
1 Lý thuyết
Việc xóa lý do là an toàn nhưng thay đổi là không phải là trong Unix, một tập tin đã xóa được không thể tiếp cận từ hệ thống tập tin, nhưng quá trình đó đã mở file (ở đây,/bin/bash) vẫn có thể đọc nó, như được giải thích here. Nó không phải là bash làm một cái gì đó đặc biệt, giống như đệm toàn bộ tập tin, nhưng nó chỉ đơn giản là đọc. (Ngay cả sau khi xóa, bạn có thể phục hồi các tập lệnh trong khi nó đang chạy, as explained here Trong bash, kịch bản dường như luôn mở như 255, /proc/<pid>/fd/255
..)
2 Emacs giải pháp
Bây giờ Emacs; để được an toàn, bạn có thể tự động hóa tất cả; thêm vào before-save-hook
một chức năng để kiểm tra xem nó là sh-mode, và xóa tự động nếu kịch bản đang mở, bằng cách kiểm tra với lsof
:
(defvar delete-open-sh-flag nil
"Used by `delete-open-sh.` If nil, deletion didn't happen.
Otherwise, the mode is saved.")
(defun delete-open-sh()
(setq delete-open-sh-flag nil)
(when (and (eq major-mode 'sh-mode)
(buffer-file-name)
(file-exists-p (buffer-file-name)))
(let ((buf (generate-new-buffer " *foo*")))
(call-process "lsof" nil; infile
buf ; dest
nil ; display
(buffer-file-name))
(unless (eq 0 (buffer-size buf))
(setq delete-open-sh-flag (file-modes (buffer-file-name)))
(delete-file (buffer-file-name)))
(kill-buffer buf))))
(defun delete-open-sh-after()
(when delete-open-sh-flag
(set-file-modes (buffer-file-name) delete-open-sh-flag)))
(add-hook 'before-save-hook 'delete-open-sh)
(add-hook 'after-save-hook 'delete-open-sh-after)
Nhưng điều này không phải là hoàn hảo. Nó lưu chế độ tập tin, nhưng đó là tất cả.
3 Giải pháp bash thuần túy
Hoặc, bạn có thể để chính kịch bản bash tự xóa. Sử dụng điều này:
# Usage: . /path/to/this-script (Always use abs path)
# Restart the caller script itself in a temporary file; this allows
# editing of the caller script file while it's run.
# Temporary file is soon deleted.
#
if [[ ! "`dirname $0`" =~ ^/tmp/.sh-tmp ]]; then
mkdir -p /tmp/.sh-tmp/
DIST="/tmp/.sh-tmp/$(basename $0)"
install -m 700 "$0" $DIST
exec $DIST "[email protected]"
else
rm "$0"
fi
dụ Cách sử dụng: lưu tập tin này trong /home/foo/a.sh:
#!/bin/sh
echo "$0 [email protected]"
. /home/foo/the-above-code.sh
echo "Again, $0 [email protected]"
Nếu bạn gọi kịch bản trên như ./a.sh 1 2 3
, kết quả là:
/home/foo/a.sh 1 2 3
/tmp/.sh-tmp/a.sh 1 2 3
Again, /tmp/.sh-tmp/a.sh 1 2 3
Điều này có thể là tốt nhất, nhưng tự chịu rủi ro.
Nó cũng được biết rằng đặt tất cả trong một cú đúp, kết thúc với exit
thực hiện công việc, như được giải thích here.
Chỉ cần thêm giải pháp này như một cách dễ dàng và sạch sẽ để bảo vệ chạy script BASH khỏi bị thay đổi:
#! /bin/bash
{
your_code;
exit;
}
Được đề cập ở phần cuối của câu trả lời của teika kazura, nhưng vẫn tiện dụng để làm nổi bật nó tôi nghĩ. – phils
- 1. Chỉnh sửa tập lệnh shell trong khi đang chạy
- 2. Chạy tập lệnh bash nhiều chuỗi từ Emacs
- 3. Trình chỉnh sửa trang và quy trình làm việc của Sitecore - làm cách nào?
- 4. Song song các quy trình PHP bằng Tập lệnh Bash?
- 5. Chạy tập lệnh bash shell trong java
- 6. Mở bộ đệm Emacs khi lệnh cố mở trình chỉnh sửa trong chế độ shell
- 7. Chạy lệnh khi tập lệnh bash bị dừng
- 8. Chạy tập lệnh bash từ tập lệnh R
- 9. Cách chạy tập lệnh bash từ chương trình C++
- 10. Làm thế nào để chạy một lệnh trước khi một tập lệnh Bash thoát?
- 11. Emacs Yaml Chỉnh sửa
- 12. Sử dụng chỉnh sửa - hợp nhất - cam kết quy trình làm việc trong TFS Source Control
- 13. grep mất màu khi chạy từ tập lệnh bash
- 14. Chạy tập lệnh bash từ Windows PowerShell
- 15. Quy trình làm việc của Python 3?
- 16. Lưu rồi làm mới lệnh phím tắt của trình duyệt trong trình chỉnh sửa
- 17. Chỉnh sửa Python trong Emacs
- 18. Kịch bản lệnh Shell để chạy nhiều quy trình
- 19. Chạy tập lệnh Bash trên dòng lệnh Windows XP
- 20. Thay đổi tên quy trình của tập lệnh Python
- 21. Chỉnh sửa tập tin Bash và giữ 500 dòng cuối
- 22. Quy trình làm việc của Xcode 4 khi làm việc với nhiều dev
- 23. Màn hình GNU chạy tập lệnh bash init
- 24. .emacs Chỉnh sửa để Luôn bắt đầu Emacs trong Chế độ Đầu cuối?
- 25. Thực hiện một tập lệnh bash khi tạo tập tin
- 26. cách viết tập lệnh để chỉnh sửa tệp JSON?
- 27. Chạy tập lệnh bash từ tập lệnh khác mà không phải đợi tập lệnh hoàn tất quá trình thực thi?
- 28. Làm cách nào để tôi có thể xử lý quy trình R trong ESS/Emacs?
- 29. thay đổi tên quy trình của tập lệnh python
- 30. CQ5 Lập trình Chạy quy trình làm việc
That sounds really đơn giản. Tôi cần phải kiểm tra kỹ xem điều này có thực sự hoạt động không. Nếu vậy, điều đó có nghĩa là hành vi lưu và đổi tên hiện tại của Emacs sẽ giữ cho vấn đề này không bị xén không? –
@MichaelHoffman Có, nếu Emacs đang thực hiện lưu và đổi tên (đây là hành vi mặc định trong hầu hết các trường hợp) thì bạn sẽ không gặp vấn đề gì cả. Lưu ý rằng tôi giả sử một unix thực sự ở đây, nếu bạn đang chạy bash trên một cái gì đó như Cygwin bạn có thể không có khả năng loại bỏ các tập tin (Tôi không chắc chắn về điều này). – Gilles
Bạn có thể chỉnh sửa câu trả lời của mình để bao gồm câu trả lời này không? Có vẻ như toàn bộ câu hỏi là không cần thiết, bởi vì Emacs làm điều đúng đắn từ chiếc hộp. –