파일 수가 많은 경우 최대한 효율적으로 이 작업을 수행하고 싶습니다. 내가 원하는 것은 내가 찾은 모든 파일의 이름을 바꾸고 해당 접미사를 제거하는 것입니다.
예를 들어:
[/tmp] $ ls -l
a.log
b.log
c.tmp
[/tmp] $ find /tmp -name "*.log" -type f -exec mv {} {%.*} \;
[/tmp] $ ls -l
a
b
c.tmp
이것은 작동하지 않습니다. 일반 bash 변수인 경우 마지막 변수 ${var%.*}
가 반환됩니다 .var
.
답변1
쉘 매개변수 확장 연산자를 사용하려면 쉘을 시작하십시오.
find ~/tmp -name '*.log' -type f -exec sh -c '
for file do
mv -i -- "$file" "${file%.*}"
done' sh {} +
다른 사람이 쓸 수 있는 디렉터리에서는 이 작업을 수행하지 않는 것이 좋습니다 . 이렇게 하면 악의적인 사용자가 파일 시스템에서 임의의 파일 /tmp
이름을 바꾸거나 파일을 다른 디렉터리로 이동할 수 있기 때문입니다 ..log
일부 구현을 사용하면 find
다음 을 mv
사용하여 보다 안전하게 만들 수 find -execdir
있습니다 mv -T
.
find /tmp -name '*.log' -type f -execdir sh -c '
for file do
mv -Ti -- "$file" "${file%.*}"
done' sh {} +
또는 시스템 호출만 수행하므로 파일을 다른 파일 시스템이나 디렉토리로 이동하려고 시도하지 않는 rename
(perl 변형)을 사용하십시오.rename()
find /tmp -name '*.log' -type f -execdir rename 's/\.log$//' {} +
또는 모든 것을 완료하려면 다음을 수행하십시오 perl
.
perl -MFile::Find -le '
find(
sub {
if (/\.log\z/) {
$old = $_;
s/\.log\z//;
rename($old, $_) or warn "rename $old->$_: $!\n"
}
}, @ARGV)' ~/tmp
그러나 perl
s Find::File
(GNU와 반대 find
)는 안전한 디렉토리 탐색을 수행하지 않으므로 이를 수행하려는 작업도 아닙니다 /tmp
.
노트.
¹ 공격자는 /tmp/. /auth.log
파일을 생성하고 find
파일 찾기와 이동 사이의 심볼릭 링크로 디렉터리를 대체할 수 있습니다 mv
(창은 쉽게 임의로 커질 수 있음 ) ."/tmp/. "
/var/log
/var/log/auth.log
/var/log/auth
² 더 나쁜 것은 공격자가 crontab을 이동할 수 있는 /tmp/foo.log
악성 crontab
코드와 /tmp/foo
심볼릭 링크를 생성할 수 있다는 것입니다./etc/cron.d
입력하다 /etc/cron.d
. 이것은 mv
(적어도 적용되고 cp
) ln
모호함이 있을 수 있는 곳입니다.이동하다그리고이사 오다. GNU mv
는 -t
(입력하다) 그리고 -T
(도착하다) 옵션.
File::Find
³를 실행하여 디렉터리를 트래버스합니다 chdir("/tmp"); read content; chdir("foo") ...; chdir("bar"); chdir("../..")...
. 따라서 누군가 디렉토리를 생성 하고 적절할 /tmp/foo/bar
때 이름을 바꿔서 ./tmp/bar
chdir("../..")
/
답변2
다음 줄은 다음과 같습니다.
find /tmp -name "*.log" -type f -exec sh -c 'f="{}"; mv "$f" "${f%.*}"' \;
셸을 시작하고, 셸 내의 적절한 변수에 {}를 할당한 다음, 셸 구문을 사용하여 문자열 작업을 적용합니다.