대체나 해석 없이 문자열 리터럴을 변수에 저장하는 방법은 무엇입니까?

대체나 해석 없이 문자열 리터럴을 변수에 저장하는 방법은 무엇입니까?

디렉토리 구조를 평면화하려면 다음을 수행하십시오.

find . -type f -exec sh -c 'mv "{}" "./`basename "{}"`"'  \;

내 프로필에 다음을 저장하고 싶습니다: $FLATTEN

-exec sh -c 'mv "{}" "./`basename "{}"`"'  \;

이렇게 하면 나중에 실행할 수 있습니다.find . $FLATTEN

너무 일찍 해석되어 변수를 저장하는 데 문제가 있습니다. 문자열 리터럴로 저장하고 가져올 때가 아닌 셸에서 사용될 때만 해석되기를 원합니다.

답변1

GNU를 사용한다면 mv다음과 같이 해야 합니다:

find . -type f -exec mv -t . {} +

다른 사람 mv:

find . -type f -exec sh -c 'exec mv "$@" .' sh {} +

{}코드를 삽입하면 안 됩니다 sh. 이는 파일 이름이 쉘 코드( `reboot`예: 이름이 지정된 파일을 사용하려는 시도) 로 해석되기 때문에 명령 주입 취약점입니다 .

quote 명령 대체는 좋은 점이지만 고대 형식( `...`대신 $(...))을 사용하고 있으므로 내부 큰따옴표 또는shBourne Shell 또는 AT&T ksh 기반 구현 에서는 작동하지 않습니다.(실제로는 불일치 "`basename "foo bar"`"(이 쉘에서는 허용됨 )로 간주된 다음 연결됩니다)."`basename "`foobar"`"

또한 다음을 수행할 때:

mv foo/bar bar

bar존재하고 디렉토리라면 실제로는 디렉토리입니다 . mv foo/bar bar/bar그렇지 mv -t . foo/bar않으면 mv foo/bar .그런 문제가 없습니다.

이제 이러한 몇 가지 매개변수(,,,,,,,)를 변수에 저장하려면 -exec배열 변수가 필요합니다. 배열을 지원하는 셸에는 , , , , , , 등이 있습니다.sh-cexec mv "$@" .sh{}+(t)cshkshbashzshrcesyashfish

ksh/bash/yash 또는 가 $FLATTEN아닌 변수를 직접 사용할 수 있으려면 합리적인 배열 구현을 갖춘 쉘이 필요합니다 : 또는 . 또한 여기서는 이러한 매개변수 중 비어 있는 것이 없습니다."${FLATTEN[@]}"$FLATTEN:q(t)cshrcesfishzsh

존재하다 rc/ es/ zsh:

FLATTEN=(-exec sh -c 'exec mv "$@" .' sh '{}' +)

존재하다 fish:

set FLATTEN -exec sh -c 'exec mv "$@" .' sh '{}' +

그런 다음 다음을 사용할 수 있습니다.

find . -type f $FLATTEN

답변2

이를 달성하고 올바른 결과를 얻으려면 쉘 함수를 사용하는 것이 더 좋습니다 ( 하위 쉘 -exec에 넣지 마십시오 ).{}

flatten () {
     ( cd "${1:-.}" && 
       find . -type f -exec sh -c 'for n; do test -e "${n##*/}" || mv "$n" "${n##*/}"; done' sh {} + )
}

또한 외부 유틸리티를 호출할 필요가 없으며 basename이미 존재하는 것을 덮어쓰려고 시도하지도 않습니다.

이를 사용하기 위해 입력하면 flatten현재 디렉토리에서 작동합니다. 디렉터리 이름을 지정하면 해당 디렉터리가 실행됩니다(해당 디렉터리 아래의 모든 파일을 해당 디렉터리의 맨 위로 복사).

답변3

함수가 아마도 가장 좋은 방법일 것입니다. 그렇지 않으면 배열이 필요하거나 다음이 필요합니다 eval.

find_array=(-exec sh -c 'mv "{}" "./`basename "{}"`"'  \;)
find . "${find_array[@]}"

또는

FLATTEN="-exec sh -c 'mv \"{}\" \"./`basename \"{}\"`\"'  \;"
eval find . $FLATTEN

답변4

기능은 어떻습니까?

flatten(){
  find "$@" -type f -exec sh -c 'mv -- "$0" "${0##*/}"' {} \;
}

용법:

> flatten .

사용하시면 선택 zsh하실 수 있습니다 . 이를 통해 명령 이름뿐만 아니라 전역적으로 삽입되는 별칭을 정의할 수 있습니다.-galias

관련 정보