rm을 사용하여 이름에 공백이 있는 여러 파일을 삭제할 수 없습니다.

rm을 사용하여 이름에 공백이 있는 여러 파일을 삭제할 수 없습니다.

나는 내 도트 파일에 대한 배포 스크립트를 작성하고 있습니다. 이 파일은 기본 Git 저장소에 저장되어 있으며 git checkout수천 건의 Git 체크아웃 오류 없이 원활하게 수행하기 위해 해당 저장소의 파일을 내 홈 디렉토리에 저장하고 있습니다. 이미 존재하는 항목( .bashrc예:) 을 삭제해야 하지만 실제로는 다음을 사용하여 검색합니다.

git --git-dir=$HOME/repos/dots --work-tree=$HOME ls-tree --full-tree --full-name --name-only -r HEAD | sed "s|^|/mnt/home/henriquehbr/|"

참고: 그 이유는 /mnt이것이 내 chroot 설치를 위한 마운트 지점이고 실제로 사용자 정의 Arch Linux 설치 이미지에서 실행하고 있기 때문입니다.

그러나 실제로 이러한 파일을 삭제하는 데 성공하지 못했습니다. 문제는 이름에 공백이 있는 파일에 있습니다( Font\ Awesome\ Icons.otf예:).

위 명령을 다음 명령 시퀀스에 전달하여 삭제할 각 파일을 참조해 보았습니다.

<get_dotfiles> | sed "s|^|\"/mnt/home/henriquehbr/|" | sed "s/$/\"/"

rm위의 내용은 작동하지 않습니다. 따옴표가 문자 그대로 파일 이름의 일부인 것처럼 처리되는 것 같습니다.

다른 시도는 좋은 루프를 만드는 것입니다 for.

dotfiles=$(git --git-dir=$HOME/repos/dots --work-tree=$HOME ls-tree --full-tree --full-name --name-only -r HEAD | sed "s|^|/mnt/home/henriquehbr/|")

for dotfile in $dotfiles; do
    echo "$dotfile" # Works properly, displays dotfile path
    rm "$dotfile" # Doesn't works, writes: '$'\n'' after the path and fails
done

답변1

널 바이트를 구분 기호로 사용하십시오.

git ls-tree -z … | xargs -0 rm

대부분의 쉘에서는 널 바이트를 변수에 넣을 수 없으므로 $(git ls-tree -z …)유용한 작업이 수행되지 않습니다.

인용문이 전달되도록 하는 인용문을 사용하려고 하면 작동하지 않습니다 rm. rm대부분의 프로그램과 마찬가지로 파일 이름만 필요합니다. "파일 이름에 나타나는 다른 문자와 마찬가지로 일반 문자입니다 . 따옴표를 삽입하는 것은 셸에서 대체에 도움이 되지 않습니다. 따옴표( $foo또는 $(mycommand …))가 없는 변수 대체 또는 명령 대체는 단지 공백으로 분할되며(각 단어는 와일드카드 패턴으로 처리됨) 이 단계에서 따옴표는 관련이 없습니다. 파일 이름 자체에 너무 "이국적인" 문자(예: 백슬래시, 탭, 큰따옴표 등)가 포함되어 있지 않은 경우 따옴표를 삽입하고 에 전달하는 것이 xargs작동할 수 있지만 and 를 사용하는 것보다 훨씬 더 복잡합니다.-0git ls-tree -zxargs -0

파일 이름에 git ls-tree따옴표로 묶인 문자(줄 바꿈 포함)가 포함되어 있지 않다고 가정하면 다음과 같이 작동합니다(다시 따옴표를 방해하지 않고).

set -f # disable wildcard expansion (globbing)
IFS='
' # set only newline as the word separator
for dotfile in $(git ls-tree …); do … 

이는 좋은 생각이 아닙니다. 런타임에 기존 파일을 강제로 삭제하려는 경우 git checkoutGit은 런타임에 파일을 기꺼이 삭제합니다 git checkout -f …. 중요한 내용이 포함된 경우 기존 파일을 체크인하는 것이 더 안전합니다.

git checkout -b original-files
git --git-dir=… ls-tree -z | xargs -0 git add
git commit -m "Original files on $HOSTNAME"
git checkout origin/master

답변2

나는 실제로 이러한 모든 복잡성을 필요로 하지 않는 더 간단한 솔루션으로 끝났습니다. 배포 중에 간단한 "강제" git 체크아웃이 이전 도트 파일을 모두 대체했습니다.

git checkout -f

소품씨는 씨가 아니다.존재하다레딧

관련 정보