다른 하위 디렉터리에 있는 일부 파일의 줄을 변경하고 싶습니다. 파일의 확장자는 항상 .dct
이며 작업 디렉터리의 다른 하위 디렉터리에 있는 하위 디렉터리에 항상 존재합니다 mod
(그러나 하위 디렉터리가 많아서 를 mod
사용합니다 find
). 하지만 내가 바꾸고 싶은 문자열은 디렉터리(Windows -> Unix)입니다.
를 통해 관련 파일을 얻을 수 있습니다 find . -type f -path '*/mod/*.dct
. 으로 관련 줄을 변경해 보았습니다 sed -e 's/cd c:\\project\\data\\/cd \/project\/data\//' $(basename {}) > $(basename {}).mod
.
나는 범인이 되는 탈출된 백슬래시로 범위를 좁혔습니다. 이것은 작동합니다:
find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c://' $(basename {}) > $(basename {}).mod"
다음은 수행되지 않습니다.
find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c:\\//' $(basename {}) > $(basename {}).mod"
이건 오류야
sed: -e expression #1, char 7: unterminated `s' command
이 char 7
부분은 탈출에 문제가 있다는 생각이 들게 합니다. 그런 것 같은데 어떻게 고칠 수 있는지 모르겠습니다. 이를 설명하기 위해 다음이 작동합니다.
find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c:\\//' $(basename {}) > $(basename {}).mod"
따라서 " 무엇이든 대체" sed -e 's/c:\\///'
로 이스케이프되고 "무엇으로 대체" 대신 "...로 대체 "(그리고 오류 발생)로 이스케이프된 것처럼 보입니다 .c:\/
sed -e 's/c:\\//'
c:\/
c:\
참고: 대신 -execdir
에 and를 사용하는 것은 약간 과잉일 수 있지만 어딘가에서 이것이 좋은 형식이라는 것을 읽었습니다.basename
-exec
답변1
질문의 핵심은 from을 호출하여 백슬래시(예: \
)를 슬래시(예: )로 바꾸는 방법입니다 . /
이렇게 하려면 문자열이 호출에 의해 한 번, 호출에 의해 두 번, 두 번 처리되기 때문에 백슬래시를 두 번 이스케이프 처리해야 합니다. 그러면 다음 정보가 제공됩니다.sed
find
find
sed
find . -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/cd c:\\\\project\\\\data\\\\/cd \/project\/data\//' $(basename {}) > $(basename {}).mod" \;
아래는 좀 더 자세한 설명입니다.
먼저 문제에 대한 약간 더 간단한 예를 설정해 보겠습니다.
# Create a target directory
mkdir -p /tmp/dir1/mod/dir2
# Create a text file containing a backslash
echo '\' > /tmp/dir1/mod/dir2/file.dct
이제 백슬래시를 사용 find
하고 sed
이를 슬래시로 바꿔 보겠습니다.
find /tmp/dir1 -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/\\/\//' $(basename {})" \;
이로 인해 다음 오류가 발생합니다.
sed: -e expression #1, char 7: unterminated `s' command
sed
이는 실행되는 명령이 다음과 같기 때문입니다 .
sed -e 's/\/\//' ./file.dct
다음 명령을 직접 실행하여 동일한 오류가 발생하는지 확인할 수 있습니다. 예:
sed -e 's/\/\//' /tmp/dir1/mod/dir2/file.dct
다음과 같은 명령을 실행하여 이를 확인할 수도 있습니다 echo
.find
find /tmp/dir1 -type f -path '*/mod/*.dct' -execdir echo "sed -e 's/\\/\//' $(basename {})" \;
명령을 수정하려면 백슬래시를 두 번 이스케이프 처리합니다.
find . -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/\\\\/\//' $(basename {})" \;
그러면 원하는 결과가 생성됩니다.
/