현재 디렉터리에 없는 파일에 이 스크립트를 적용할 수 없는 이유는 무엇입니까?

현재 디렉터리에 없는 파일에 이 스크립트를 적용할 수 없는 이유는 무엇입니까?

~/bin/align-tablesemacs stackexchange에서 이 스크립트를 얻었습니다.

#!/bin/sh
# -*- mode: shell-script -*-
#
# tangle files with org-mode
#
DIR=`pwd`
FILES=""

# wrap each argument in the code required to call tangle on it
for i in $@; do
FILES="$FILES \"$i\""
done

emacs -Q --batch \
--eval "(progn
     (require 'org)(require 'org-table)
     (mapc (lambda (file)
            (find-file (expand-file-name file \"$DIR\"))
            (org-table-map-tables 'org-table-align)
            (write-file file nil)
            (kill-buffer)) '($FILES)))"

.org이 스크립트를 디렉토리의 모든 파일 에 적용하고 싶습니다 ~/foo. 내 작업 디렉토리가 /foo다음이면 릴리스가 $ align-tables *.org완벽하게 작동합니다. 그러나 다른 디렉토리에 있으면 $ align-tables ~/foo/*.org오류가 발생합니다.

Opening output file: no such file or directory, ~/foo/foo/#bar.org#

오류 메시지에 대상 디렉터리가 두 번 나열되어 있으므로 스크립트의 해당 줄에 문제가 있다고 가정 DIR='pwd'하지만 스크립트를 수정하는 방법을 잘 모르겠습니다.

align-tables나의 동기는 다양한 디렉토리에서 작동하는 Perl 프로그램을 작성하고 있다는 것입니다 .

내 스크립트가 협력하도록 하는 방법에 대한 아이디어가 있습니까?

답변1

완전성을 기하기 위해 이 문제는 셸에서 순수하게 해결할 수 있습니다.

for i in "$@"; do
  pushd "$(dirname "$i")"
  DIR=`pwd`
  FILES="\"$(basename "$i")\""
  emacs -Q --batch \
    --eval "(progn
     (require 'org)(require 'org-table)
     (mapc (lambda (file)
            (find-file (expand-file-name file \"$DIR\"))
            (org-table-map-tables 'org-table-align)
            (write-file file nil)
            (kill-buffer)) '($FILES)))"
  popd
done

그러면 각 파일의 포함 디렉터리로 변경된 다음 emacs상대 경로 이름을 사용하여 해당 단일 파일에 대해 기존 명령을 실행한 다음 다시 전환합니다.

이는 비효율적이며 잘못될 수 있는 일이 많습니다(특히 elisp를 삽입할 때 문제를 일으킬 수 있는 이상한 경로 이름*). 그리고 확실히 emacs 자체 내에 더 나은 솔루션이 있지만 원본 스크립트만큼 잘 작동합니다.


* 예를 들어 다음과 같은 파일이 있다고 가정합니다.

"

따옴표는 문자 그대로 포함되고 닫는 문자열 리터럴로 처리되므로 elisp 스크립트에서 구문 오류가 발생합니다. 다른 사람이 존재하는 파일 이름을 제어할 수 있다면 임의의 코드를 실행하는 코드를 생성할 수 있지만 해당 파일 이름이 없어도 문제가 발생할 수 있습니다.

답변2

\[?*"~현재 디렉터리의 경로나 명령줄에 전달된 파일 이름에 특수 문자(공백, )가 포함되어 있으면 이 스크립트는 다양한 방식으로 실패합니다. 그러나 "길들인" 파일 이름의 경우 보기에는 좋아 보입니다(지나치게 복잡하지만 나쁘지는 않습니다).

#bar.org#자동 저장 파일입니다. Emacs는 수정 시 연관된 버퍼를 생성하고 bar.org, 버퍼를 저장할 때 삭제합니다.

파일 이름, 특히 그 부분에 무슨 일이 일어나고 있는지 잘 모르겠습니다 ~/foo/foo/. 하지만 지어낸 이름으로는 진단하기가 어렵습니다. 해당 부분에 대한 도움이 필요하면 실제 파일 이름이 포함된 예제를 게시해 주세요. /tmp사용자 이름이 공개되는 것을 원하지 않으시면 아래 파일을 드롭해 주세요.

문제는 Org 파일의 다른 파일에 대한 참조와 관련이 있을 수 있습니다. 내용을 보지 않고는 알기 어렵습니다. 도움이 필요하면 실제 파일 내용과 스크립트 실행의 전체 출력을 게시해 주세요.

명령줄에 전달된 모든 파일을 조작하는 더 쉬운 방법이 있습니다. 먼저 게시한 스크립트는 FILES변수에 파일 이름이 포함된 일부 Emacs 코드를 빌드합니다. 하지만 이렇게 할 필요는 없습니다. emacs명령줄에 파일 이름을 전달하고 argv변수에서 사용하면 됩니다. 파일을 열 때 절대 파일 이름을 만들 필요가 없습니다. 이름을 find-file.

#!/bin/sh
emacs --batch -l org -l org-table --eval "
    (mapc (lambda (file)
            (find-file (file))
            (org-table-map-tables 'org-table-align)
            (save-buffer)
            (kill-buffer)
          argv)
" "$@"

관련 정보