특정 확장자를 인수로 사용하여 파일을 기대하는 프로그램을 속이기 위해 프로세스 대체를 사용합니까?

특정 확장자를 인수로 사용하여 파일을 기대하는 프로그램을 속이기 위해 프로세스 대체를 사용합니까?

제 사용 사례는 다음과 같습니다. 명령줄 유틸리티는 명령줄의 melt확장자 .melt와 함께 파일 이름을 받아 열 수 있습니다. 예를 들어, 이것은 적절한 test_p.melt파일입니다:

colour:blue
out=24

colour:red
out=48

...를 열고 재생합니다 melt test_p.melt.

문제는 .melt파일이 주석을 지원하지 않는다는 것입니다. 그랬으면 좋겠습니다(예를 들어 a가 포함된 인수를 포함하여 구문 분석할 수 없는 인수가 포함된 모든 줄에 대해 오류 메시지가 표시됩니다 #). 주석이 달린 파일은 다음과 같습니다 test_c.melt.

# master comment here

colour:blue  # this is blue!
out=24

colour:red
out=48

이것을 직접 열면 다음이 melt제공됩니다.

$ melt test_c.melt
Failed to load "# master comment here"
...

...그리고 블루 스크린이 표시되지 않습니다.

그래서 저는 댓글을 달 수 있겠다고 생각했어요.그래도그런 다음 Bash 프로세스 대체를 사용하여 파일을 필터링하고 sed이를 애플리케이션에 제공하기만 하면 됩니다 melt. 먼저 로 테스트를 시도했는데 cat성공했습니다.

$ cat <(sed 's/#.*$//' test_c.melt)



colour:blue  
out=24

colour:red
out=48

... 좋아 보인다;하지만, 으로 시도하면 melt내 속임수가 간파됩니다.

$ melt <(sed 's/#.*$//' test_c.melt)
Failed to load "/dev/fd/62"
Failed to load "/dev/fd/62"

기본적으로 Melt는 프로세스 대체를 위해 제공된 파이프 Bash의 파일 이름을 얻었습니다. 하지만 불행하게도 Melt 는 직접 melt처리한다는 것입니다 . argv[i]파일의 경우 .melt파일 이름에 확장자가 표시되어야 합니다. 그렇지 않으면 프로세스가 실패합니다.

그래서 내 질문은: 어떻게 프로세스 대체를 사용할 수 있습니까? 따라서 파이프의 파일 이름은 특정 확장자를 갖습니다. 이 경우에는 .melt? 기본적으로 대체의 결과로 파이프 파일 이름이 가 되길 원하며 /dev/fd/62.melt이는 통과할 것이라고 생각합니다.

주의: 물론, 언제든지 다음을 수행할 수 있습니다.

sed 's/#.*$//' test_c.melt > test_c_temp.melt
melt test_c_temp.melt

... 하지만 먼저 여기에는 두 개의 명령이 있습니다. 그리고 저는 한 줄짜리 파이프라인을 원합니다. 또 다른 경우에는 나중에 임시 파일을 제거하는 것에 대해 생각하는 것이 마음에 들지 않는 또 다른 문제를 야기합니다.

Bash 프로세스 대체를 통해 이것이 가능합니까? 아니면 표준 Linux 도구를 사용하여 가능합니까?

답변1

melt수정된 파일 복사본을 표시하는 파일 시스템을 가리키는 것이 가능합니다 .퓨즈일반 프로그램으로 구현되고 권한이 필요하지 않은 파일 시스템 드라이버를 빌드하는 일반적인 방법입니다. 있다주변에 많은 FUSE 파일 시스템이 있습니다., 그리고 그들 중 하나가 당신을 도울 수 있는 좋은 기회가 있습니다. 아이디어는 .melt파일을 읽을 때 "실제" 파일을 읽지만 주석은 필터링되는 마운트 지점을 제공하는 것입니다.

스크립트FS유망해 보입니다(그러나 나는 그것을 사용해 본 적이 없습니다). 다음과 같이 작동해야 합니다.

mkdir ~/uncommented-melt
scriptfs -p "$HOME/bin/uncomment-melt;&*.melt" ~/work ~/uncommented-melt

파일을 ~/work포함하고 있는 트리의 루트는 어디에 있습니까 ?.melt~/bin/uncomment-melt

#!/bin/sh
sed 's/#.*$//' "$1"

그런 다음 주석이 포함된 파일이 있으면 를 ~/work/test_c.melt실행할 수 있습니다 melt ~/uncommented-melt/test_c.melt.

기타 잠재적으로 도움이 되는 FUSE 파일 시스템:

  • 실행— 쉘 스크립트를 사용하여 간단한 FUSE 드라이버를 구축할 수 있습니다.
  • AVFS또는 파일을 투명하게 압축 해제하는 기타 FUSE 파일 시스템: 주석 제거를 압축 해제 규칙으로 정의합니다.

답변2

셸을 사용하면 접미사를 지정할 수 있는 프로세스 대체 형식(파일 및 파이프 대신 임시 파일을 사용 )을 zsh사용할 수 있습니다 .=(...)/dev/fd/x

(TMPSUFFIX=.melt; melt =(sed 's/#.*$//' test_c.melt))

자세한 내용은 info zsh TMPSUFFIX( info페이지가 설치되어 있다고 가정하면 패키지를 설치해야 할 수도 있음 )을 참조하세요 .zsh-doc

답변3

좋아, 내 특별한 경우에는 이러한 종류의 Melt 스크립트가 명령줄 인수로 엄격하게 해석되어야 한다는 것이 밝혀졌습니다. 따라서 OP에 있는 것만으로는 sed충분하지 않습니다(게다가 설정할 수 있는 프로필과 같은 다른 항목도 있습니다). 그래서 여기에 내가 하게 된 일이 있습니다. 아마도 OP 제목이 다룰 다른 경우에 영감을 줄 수 있을 것입니다.

나는 결국 이것을 사용하기로 결정했습니다. test.shmelt실제로 bash주석이 달린 melt스크립트 코드가 포함된 스크립트인 파일을 만듭니다. 이 파일을 실행 가능하게 만듭니다 chmod +x test.shmelt. 그런 다음 스크립트를 편집한 후 ./test.shmelt.

실행 시 에 "정리된" test.melt파일이 생성되고 대신 이 파일이 /tmp호출됩니다 melt. 일반적 으로 melt프로그램이 끝난 후에도 터미널에서 계속 실행되므로 SIGINT에 트랩을 사용하면 Ctrl-C를 누르면 이 임시 파일을 정리할 수 있습니다(그러나 꼭 그럴 필요는 없습니다).

그런 식으로 여전히 의견이 있습니다. 소스 파일에서 빠르게 편집하고 Melt를 실행하여 결과를 확인할 수 있습니다. 나중에 사용할 수 있도록 댓글을 "정리"한 파일도 준비하세요.

코드는 다음과 같습니다 test.shmelt.

#!/bin/bash

# call with: ./test.shmelt


#TMLTFILE="test.melt" # for final export
TMLTFILE="${0%%.shmelt}.melt" # for final export

function finished() { echo ; } ; # use this when testing or montaging to keep exported (tmp) .melt file; uncomment the below to remove the tmp file
#~ function finished() { rm /tmp/"$TMLTFILE"; echo "fin1 $0" ; } ; trap finished SIGINT ;

echo 'Remember `pulseaudio --start` to hear audio with `melt`!'
pulseaudio --check
if [ $? -ne 0 ]; then
    pulseaudio --start
fi

DIRNAME=$(readlink -f $(dirname $0))
PROFILE="square_ntsc"


echo "
# the profile doesn't work from here;
# still has to be specified on command line
# but including it here so the path is saved for testing
#~ -profile
#~ ${PROFILE}

-video-track

  # can avoid pixmap: here, but that s the producer;
  # qimage: also works
  # NB it is NOT '-out 1645'; but 'out=1645'!!
  /media/myimg/%05d.bmp
  in=0
  out=1645
  #~ length=1645
  #~ loop=0
  #~ eof=stop

-audio-track

  /media/mysnd/snd.wav
  in=0
  out=1645
  #~ loop=0
  #~ eof=stop

#-consumer xml # doesn't work here

" | sed -e 's/#.*$//' -e 's/^[[:space:]]*//' -e '/^[[:space:]]*$/d' -e 's/[[:blank:]]*$//' > ${TMLTFILE}

# the sed: remove comments; remove indents; remove empty lines; remove spaces at end of line


# eof: one of: stop, loop, continue or pause (eof=stop)
# to loop, use `melt eof=loop ...` (but make sure first,
#  that the edit as a whole stops - use xml to check!)
# due to caching issues, preview pieces (up to ~300 frames) like this:
melt eof=loop -profile ${PROFILE} ${TMLTFILE} in=200 out=400

# must have profile here, for checking w/ -consumer xml (else segfault)
# this command may add additional producers to the xml!:
## melt -profile ${PROFILE} ${TMLTFILE} -consumer xml

# use this to generate xml if needed:
#melt -profile ${PROFILE} $(cat ${TMLTFILE} | tr '\n' ' ') -consumer xml

# if exited normally, cleanup:
finished

답변4

시간이 좀 지났지만 나에게 도움이 될 만한 방식으로 제목 질문에 답해 보도록 하겠습니다.

이는 다음과 관련이 있습니다.BASH 프로세스 대체가 일부 명령에서 작동하지 않는 이유는 무엇입니까?

그래서 제가 해결하려고 했던 구체적인 문제는 다음과 같습니다.

  1. 이미지 변환기가 있습니다.
  2. [임의의 형식 삽입]을 BMP/PNM/TGA와 같은 간단한 형식으로 변환합니다.
  3. JPEG로 변환하고 싶으므로 ImageMagick과 연결해야 합니다 convert.
  4. 임시 파일을 사용하고 싶지 않습니다.

따라서 불행하게도 이 도구는 출력 파일 이름의 확장자에서 출력 형식을 파생시키기 때문에 stdout/fds/pipes로 출력하는 것을 좋아하지 않습니다. 그럼 어떻게 속일 수 있을까?

적절한 확장자를 가진 심볼릭 링크를 생성 /dev/fd/N하고 이를 "임시 파일"로 사용합니다.

예:

ln -s /dev/fd/4 temp.pnm
[TOOL] -i [INPUTFILE] -o temp.pnm 4>&1 | convert - [OUTPUT.JPG]

관련 정보