*를 사용한 Xargs 및 rm

*를 사용한 Xargs 및 rm

다음 명령을 실행하려고 합니다.

ls -d a* | xargs -i sudo rm -rf {}/*

문제는 해당 섹션을 추가 /*하면 명령이 작동하지 않는다는 것 입니다. 디렉토리 내용(디렉토리 자체가 아님)을 삭제하고 싶습니다.

답변1

무엇에 대해 rm -r a*/*? 이렇게 하면 문제가 해결될 것입니다.

답변2

이와 같은 명령은 rm와일드카드를 확장하기 위해 셸을 사용하므로 어딘가에서 셸을 호출해야 합니다.

아마도

 ls -d a* | xargs -i sh -c sudo rm -rf {}/*

답변3

(경고하다: 아직 이 명령을 테스트하지 않았습니다. 오타나 오류가 있을 수 있습니다. echoor 및 no를 먼저 사용하여 ls모든 것을 시도해 보세요 sudo. )

일반적인 조언: xargs어떤 일을 하는 가장 쉬운 방법은 거의 없습니다. 그렇지 않은 경우 -i(더 이상 사용되지 않으며 -I {}대신 이식성을 사용함) xargs표준 또는 공통 도구로 생성된 입력 형식이 필요하지 않습니다. 를 사용하면 -Ixargs가지 용도가 있지만 파이프를 사용하면 더 간단합니다 find.find -exec

확장하려면 쉘이 필요하며 {}/*, 해당 쉘은 {}작업할 실제 경로로 대체되어야 합니다. 간단한 해결책은 쉘에서 한 줄씩 수행하는 것입니다. 점 파일이 생략되기 때문에 세 가지 패턴 모두 디렉터리의 모든 파일을 캡처하는 데 사용됩니다. 일부 패턴이 어떤 파일과도 일치하지 않더라도 기존 파일을 참조하지 않는 인수는 무시되기 *때문에 중요하지 않습니다 .rm -f

… |
while read -r line; do
  sudo rm -rf -- "$line"/* "$line"/.[!.]* "$line"/..?*
done

쉘이 와일드카드를 수행하려면 어떤 시점에서 파일을 하나씩 처리해야 하기 때문에 Xargs는 여기서는 쓸모가 없습니다. 그러나 일반적인 기술이 유용할 수 있으므로 xargs에서 셸로 파일 이름을 반환하는 방법이 있습니다. 는 셸에 대한 인수 _입니다 (부분적으로 후속 인수 $0로 돌아갈 필요가 없고 로 시작하더라도 모든 것이 작동 하도록 보장하기 위해 존재합니다 . 그렇지 않으면 셸에 대한 옵션으로 처리됩니다). 여기에는 두 가지 접근 방식이 있습니다. 즉, 쉘이 인수를 반복하도록 하거나 xargs에게 각 쉘 호출에 단일 인수를 전달하도록 지시하는 것입니다.$0$1-

… | xargs -I {} sudo sh -c 'for x; do rm -rf -- "$x"/* "$x"/.[!.]* "$x"/..?*; done' _ {}
… | xargs -I {} -n 1 sudo sh -c 'rm -rf -- "$1"/* "$1"/.[!.]* "$1"/..?*' _ {}

나는 이것이 ls -d a*장난감 예제이고 한 줄에 하나의 파일 이름을 생성하는 더 복잡한 명령이 있다고 가정합니다. 이 ls -d a*됩니다 .아니요ls대부분의 구현에서는 인쇄할 수 없는 문자를 투명하게 출력하지 않기 때문에 작동합니다 . 검색 명령어인 경우 -exec와 같은 를 이용해주세요.

find a* -exec sh -c 'rm -rf -- "$1"/* "$1"/.[!.]* "$1"/..?*' _ {} \; -prune

답변4

또 다른 옵션은 xargs를 호출하는 대신 쉘 루프를 사용하는 것입니다.

예를 들어

ls -d a* | while read dir; do sudo rm -rf "$dir"/*; done;

주로 예를 들기 위해 파이프 중앙에 쉘 구성을 배치하여 이 두 가지 기술을 결합할 수도 있습니다.

ls -d a* | while read dir; do ls -d "$dir"/*; done | xargs -d \\n rm -rf

xargs에 대한 옵션은 -d단순히 인수 사이의 구분 기호가 개행 문자임을 지정하여 공백이 포함된 파일 이름과 관련된 잠재적인 치명적인 문제를 방지합니다(예: deadly / file)

관련 정보