find로 찾은 파일을 덮어쓰시겠습니까?

find로 찾은 파일을 덮어쓰시겠습니까?

파일 목록이 있습니다

-rw-rw-r-- 1 t t 24813 Oct 23  2002 fig8_21.gif
-rw-rw-r-- 1 t t  2259 Oct 23  2002 fig8_21t.gif
-rw-rw-r-- 1 t t 35331 Oct 23  2002 fig8_23.gif
-rw-rw-r-- 1 t t  2610 Oct 23  2002 fig8_23t.gif
-rw-rw-r-- 1 t t 19970 Oct 23  2002 fig8_24.gif
-rw-rw-r-- 1 t t  2019 Oct 23  2002 fig8_24t.gif
-rw-rw-r-- 1 t t 54623 Oct 23  2002 fig8_3.gif
-rw-rw-r-- 1 t t  3657 Oct 23  2002 fig8_3t.gif
-rw-rw-r-- 1 t t 35861 Oct 23  2002 fig8_4.gif
-rw-rw-r-- 1 t t  2344 Oct 23  2002 fig8_4t.gif

예를 들어 복사하여 덮어쓰기를 <...>t.gif사용하여 덮어쓰고 싶습니다 .<...>.giffig8_4.giffig8_4t.gif

나는 <...>t.gif이 파일들을 찾는 것부터 시작한다 find . -regex ".*t\.gif". 그런 다음 파일 이름 제거를 사용하고 싶은데 basename다음 경고가 나타나는 이유는 무엇입니까?

$ find .  -regex ".*t\.gif" -execdir basename {} \;  
find: The relative path `~/program_files/internet/SSH_tunneling/' is included in the PATH environment variable, which is insecure in combination with the -execdir action of find.  Please remove that entry from $PATH

$ find .  -regex ".*t\.gif" | xargs basename 
basename: extra operand ‘./f10_1t.gif’

임무를 어떻게 진행하나요?

사용하면 안되나요 find?

답변1

예, 가능합니다. 한 가지 접근 방식은 다음과 같습니다.

cd /den/of/gifs && \
for f in ./*t.gif; do
    mv -- "${f%%t.gif}.gif" "$f"
done

가장 긴 일치 문자열을 제거하기 위한 ${var%%pattern}표준/POSIX 구문입니다 .sh무늬연말부터 시작 $var.

답변2

더 작고 빠르게 만들려면 다음을 사용할 수 있습니다 parallel.

parallel mv {} {.}t.gif  :::: <(find . -regex '.+[0-9].gif')

after 표현식은 ::::매개변수를 제공합니다 parallel. 그런 다음 이 매개변수를 사용하십시오 {}. {.}파일 확장자가 없는 매개변수를 나타냅니다 . 따라서 이 예 에서는 {}가 없는 파일의 파일 이름이 됩니다 . 예를 들어 .tfig8_4.gif{.}fig8_4

답변3

findsum 을 계속 사용하려면 basename다음과 같이 하면 됩니다.

find . -name "*.gif" ! -name "*t.gif" -execdir sh -c '
  cp -- "$0" "$(basename "$0" .gif)t.gif"' {} \;

성능 및 리소스 관점에서 볼 때 이는 최선의 선택이 아닙니다.

답변4

귀하의 오류에 관해서 :

find: 상대 경로 '~/program_files/internet/SSH_tunneling/'은 PATH 환경 변수에 포함되어 있으며 find의 -execdir 작업과 함께 사용하기에는 안전하지 않습니다. $PATH에서 이 항목을 제거하십시오.

당신 ~/program_files/internet/SSH_tunneling/$PATH말 그대로 ~. 물론아니요당신의 의미메인 디렉토리. 대신에 다음과 같은 뜻이 있습니다.상대 경로 ~/program_files/internet/SSH_tunneling/, 즉 현재 디렉토리 내의 디렉토리 내에 있습니다 SSH_tunneling.internetprogram_files~

-execdir명령을 실행하려는 디렉토리로 $PATH이동하는 상대 디렉토리를 좋아하지 마십시오 . chdir()예를 들어, 디렉토리 트리에서 내림차순으로 내려가는 동안 디렉토리 도 포함하는 find파일 gif이 발견되고 가 있으면 결국 실행될 수 있습니다../some-dir~./some-dir/~/program_files/internet/SSH_tunneling/basename저것 basename.

다음이 있을 수 있습니다.

PATH="~/program_files/internet/SSH_tunneling/"

귀하의 경우에는 다음 ~/.bash*과 같아야 합니다.

PATH=~/program_files/internet/SSH_tunneling/

또는

PATH="$HOME/program_files/internet/SSH_tunneling"
 $ find .  -regex ".*t\.gif" | xargs basename 
 basename: extra operand ‘./f10_1t.gif’

xargsbasename가능한 한 많은 매개변수를 사용하여 실행됩니다. basename최대 2개의 매개변수가 필요하며 첫 번째 매개변수는 경로이고 두 번째 매개변수는 모드입니다. 따라서 귀하의 명령은 의미가 없습니다.

또한 xargs기본적으로 find목록은 입력 시 공백(로케일 및 구현에 따라 공백, 탭 등 가능)과 줄바꿈(모두 파일 이름에 나타날 수 있음)으로 구분되어야 합니다. 그리고 따옴표는 특별하게 처리됩니다. 이는 형식 출력 프로세스가 아닙니다 find.

find다음과 같이 출력됩니다.

./path/to/picture from "The End of the World".gif

이는 , , xargs의 3가지 다른 매개변수로 이해됩니다 . 예상되는 형식으로 패턴이 출력되지 않습니다 . 여기서는 다음과 같습니다../path/to/picturefromThe End of the World.giffindxargs

./path/to/picture\ from\ \"The\ End\ of\ the\ World\".gif

또는

'./path/to/picture from "The End of the World".gif'

일부 구현에서는 공백/줄 바꿈+따옴표 대신 NUL 구분 목록을 처리하는 xargs옵션을 지원하고 일부 구현에는 해당 형식으로 파일 이름을 출력하는 조건자가 있습니다(그렇지 않은 경우 대신 이를 사용할 수 있음).-0find-print0-exec printf '%s\0' {} +

그래서 이렇게 :

find .  -name "*t.gif" -print0 | xargs -r0 -I {} basename {} t.gif

이는 전반적인 목표에 큰 도움이 되지 않습니다. 대신 다음과 같은 것을 원할 것입니다.

find . -name '*t.gif' -type f -exec sh -c '
  for f do
    cp "${f%t.gif}.gif" "$f"
  done' sh {} +

또는 다음을 사용하여 zsh:

autoload zmv # if not already in ~/.zshrc
zmv -C '(**/)(*)t.gif(#qD.)' '$1$2.gif'

관련 정보