파일 목록이 있습니다
-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
사용하여 덮어쓰고 싶습니다 .<...>.gif
fig8_4.gif
fig8_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
. 그런 다음 이 매개변수를 사용하십시오 {}
. {.}
파일 확장자가 없는 매개변수를 나타냅니다 . 따라서 이 예 에서는 {}
가 없는 파일의 파일 이름이 됩니다 . 예를 들어 .t
fig8_4.gif
{.}
fig8_4
답변3
find
sum 을 계속 사용하려면 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
.internet
program_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’
xargs
basename
가능한 한 많은 매개변수를 사용하여 실행됩니다. basename
최대 2개의 매개변수가 필요하며 첫 번째 매개변수는 경로이고 두 번째 매개변수는 모드입니다. 따라서 귀하의 명령은 의미가 없습니다.
또한 xargs
기본적으로 find
목록은 입력 시 공백(로케일 및 구현에 따라 공백, 탭 등 가능)과 줄바꿈(모두 파일 이름에 나타날 수 있음)으로 구분되어야 합니다. 그리고 따옴표는 특별하게 처리됩니다. 이는 형식 출력 프로세스가 아닙니다 find
.
find
다음과 같이 출력됩니다.
./path/to/picture from "The End of the World".gif
이는 , , xargs
의 3가지 다른 매개변수로 이해됩니다 . 예상되는 형식으로 패턴이 출력되지 않습니다 . 여기서는 다음과 같습니다../path/to/picture
from
The End of the World.gif
find
xargs
./path/to/picture\ from\ \"The\ End\ of\ the\ World\".gif
또는
'./path/to/picture from "The End of the World".gif'
일부 구현에서는 공백/줄 바꿈+따옴표 대신 NUL 구분 목록을 처리하는 xargs
옵션을 지원하고 일부 구현에는 해당 형식으로 파일 이름을 출력하는 조건자가 있습니다(그렇지 않은 경우 대신 이를 사용할 수 있음).-0
find
-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'