
find
내 Qnap NAS에 매개변수가 부족한 명령이 있어서 -exec
파이프로 연결해야 합니다. 셸은 다음과 같습니다: GNU bash, 버전 3.2.57(2)-release-(arm-unknown-linux-gnueabihf)
현재 디렉터리의 모든 하위 디렉터리(파일 아님)에 setgid 비트를 설정하려고 합니다.
이것은 작동하지 않습니다:
find . -type d | xargs chmod g+s $1
"$1"
, 등 "$(1)"
을 사용해 $("1")
도 작동하지 않습니다. 그들은 모두 chmod
두 개 이상의 매개변수로 공백을 포함하는 디렉토리 이름이 전달되고 있음을 나타냅니다(어떤 매개변수가 지원되는지에 대한 표준 도움말 메시지가 표시됩니다).
xargs
꼭 필요하지 않으면 사용하지 않습니다 . 어쨌든 긴 이름 때문에 질식할 것 같아요, 그렇죠?
다음과 그 변형은 작동하지 않습니다.
find . -type d | chmod g+s
find . -type d | chmod g+s "$1"
awk
따옴표를 사용 하거나 삽입하는 방법을 생각해 보았지만 sed
이를 수행하는 더 쉬운 방법이 있다고 생각해야 합니다. 사람들은 이전에 무엇을 했나요 -exec
? (슬픈 점은 제가 1995년쯤에 알았을 수도 있지만 오랫동안 잊어버렸다는 것입니다.)
추신: 이러한 다양한 디렉터리 이름에는 유니코드 문자, 기호 ?
등이 포함됩니다. 원래는 다소 허용적인 macOS에서 가져온 것입니다. 즉, Windows가 인스턴스를 질식하지 않도록 모든 ?
인스턴스를 유니코드 문자와 같은 것으로 대체해야 할 것입니다. ⁇
하지만 이를 위해서는 find
이 크리플웨어 버전의 find
.
답변1
의 출력은 find
개행 문자로 구분된 파일 이름을 내보냅니다 . 1 .xargs
이것은 원하는 형식이 아니며 원하는 find
형식을 생성할 방법이 없습니다 xargs
. 입력을 공백으로 구분된 항목으로 구문 분석하고 \'"
인용에 사용됩니다. 의 일부 버전에서는 xargs
개행으로 구분된 입력을 사용할 수 있지만 find
표준 옵션이 부족한 경우에도 사용할 가능성이 있습니다 xargs
.
find . -type d | xargs chmod g+s
디렉터리 이름에 공백이나 \'"
. 없음에 유의하십시오 $1
. 이는 쉘에 의미가 있지만 의 출력을 구문 분석 find
하고 에 공급하는 데에는 쉘이 관여하지 chmod
않습니다 xargs
.
find
has -print0
및 xargs
has 인 경우 -0
이러한 옵션을 사용하여 임의의 파일 이름과 함께 작동하는 null로 구분된 파일 이름을 전달할 수 있습니다.
find . -type d -print0 | xargs -0 chmod g+s
xargs
표준 옵션을 지원하는 경우 -I
이를 사용하여 공백으로 구분된 따옴표 대신 각 행을 항목으로 처리하도록 지시할 수 있습니다. 이것은 공백에는 대응하지만 \"'
줄 바꿈에는 대응하지 않습니다.
find . -type d | xargs -I {} chmod g+s {}
대신 쉘을 사용하여 줄을 반복할 수 있습니다 xargs
. 이는 개행 문자가 포함되지 않은 모든 파일 이름에 적용됩니다.
find . -type d | while IFS= read -r line; do chmod g+s "$line"; done
두 가지 솔루션 모두 개행 문자가 포함되지 않은 파일 이름에서만 작동합니다. 개행 문자가 포함된 파일 이름 사용 의 출력은 find
구문 분석하기 어려운 한 가지 경우를 제외하고는 모호합니다. find
여러 개의 슬래시를 자발적으로 내보내지 않으므로 //
탐색할 디렉터리 경로를 입력하면 출력에서 이를 인식할 수 있습니다. 다음은 이 사실을 사용하여 출력을 find
의 입력 형식으로 변환하는 최소한의 테스트를 거친 코드입니다 xargs
.
chars=$(printf '\t "'\\\')
{ find .//. -type d; echo .// } | LC_ALL=C sed -n '
s/['"$chars"']/\\&/g
/^\.\/\// {
x
s/\n/\\&/g
p
b
}
H' | LC_ALL=C xargs chmod g+s
1 보다 정확하게는 개행 문자로 종료됩니다(성 뒤에 개행 문자가 있습니다).
답변2
bash를 사용하여 재귀를 직접 수행할 수 있습니다. 다음과 같은 것 :
shopt -s nullglob dotglob
recurse_chmod () (
cd "$1"
for d in ./*/
do
if [ -L "$d" ]; then continue; fi
chmod g+s "$d"
recurse_chmod "$d"
done
)
recurse_chmod .
답변3
구분 기호로 \0을 사용하도록 xargs에 지시할 수 있습니다.find . -type d -print0 | xargs -0 chmod g+s
또는
find . -type d | xargs -I{} -d '\n' chmod g+s "{}"
. 구분 기호로 \n을 사용합니다.