공백(각 파일 이름에 여러 개)이 포함된 파일과 디렉터리가 여러 개 있고 이를 제거하려고 합니다. 나는 rename
정규식을 이해하지 못하는 "어리석음"에 갇혀 있습니다. 지금까지 나는 다음과 같은 것으로 끝났습니다.
find . -maxdepth 1 -type d -print0 | perl -pe 'print $_; s/\s+/_/g' | xargs -n 2 -0 mv
find
이것을 Perl 정규식의 힘과 결합하려고 합니다(현재는 첫 번째 레벨 디렉토리의 이름만 바꾸고 싶습니다. xargs
공백을 구분 기호로 사용하는 문제를 피하려고 합니다 ).-print0
올바른 방향으로 가고 있지만(결국 변화하면 원하는 것을 얻을 수 mv
있음 echo
) 제대로 작동하지 않습니다.
일반적인 조언을 주시면 대단히 감사하겠습니다!
답변1
perl
이미 다음 을 사용하여 새 이름을 생성 했으므로 rename
:perl
find . -maxdepth 1 -type d -print0 |
perl -0nE '$o=$_; s/\s+/_/g; rename $o, $_'
/r
새로운 방법을 사용하여 다음을 수행 할 수도 있습니다 .
perl -0nE 'rename $_, s/\s+/_/gr or die "$_: $!\n"'
답변2
답변3
어쨌든 당신은 Perl을 사용하고 있는데 Perl에서 모든 것을 수행하는 것은 어떻습니까?
perl -w -Mstrict -MFile::Find -E 'finddepth(sub { rename $_, s/\s+/_/gr }, ".")'
( -w
및 -Mstrict
옵션은 필수는 아니지만 경고 및 엄격 모드를 활성화하므로 좋은 습관입니다.)
위의 코드는 파일 이름을 이미 존재하는 이름으로 바꾸고 해당 이름의 이전 파일을 삭제합니다. 이를 방지하려면 다음을 수행할 수 있습니다.
perl -w -Mstrict -MFile::Find -E 'finddepth(sub { my $n = s/\s+/_/gr; rename $_, $n unless -e $n }, ".")'
또한 모든 오류는 rename
자동으로 무시됩니다. 이는 수정하기가 특별히 어렵지는 않지만 한 줄의 코드에 비해 약간 장황합니다. 그러나 언제든지 다음과 같은 실제 Perl 스크립트를 작성할 수 있습니다.
#!/usr/bin/perl
use warnings;
use strict;
use File::Find qw(finddepth);
use Errno qw(EEXIST);
sub safe_rename {
my($old, $new) = @_;
$! = EEXIST and return if -e $new;
rename $old, $new;
}
finddepth(sub {
my $new = s/\s+/_/gr;
return if $_ eq $new;
safe_rename $_, $new or warn "Error renaming $_ to $new in $File::Find::dir: $!\n";
}, @ARGV);
예를 들어 이 스크립트를 다른 이름으로 저장하면 rename_space.pl
이를 실행할 수 있고 perl rename_space.pl
(또는 실행 가능하게 ./rename_space.pl
만들 수도 있음) 명령줄 인수로 chmod
처리할 디렉터리를 전달할 수 있습니다(예: )..
답변4
관점 측면에서 생각하는 것보다 find | perl | xargs
각 파일을 반복하는 것이 더 쉽고 명확하며 안전한 경우가 많습니다 . 이름이 변경된 디렉토리는 여기서 트랩이므로 루프 본문에 두 개 이상의 행이 있습니다. 이 작업은 모든 언어로 수행할 수 있지만 다음은 순수 bash로 수행한 것입니다( 명령 제외 mv
).
#!/usr/bin/env bash
set -eu
shopt -s nullglob globstar
for f in ./**/*' '*; do
directory="${f%/*}"
filename="${f##*/}"
# The direcory would be renamed in a previous iteration
# (because bash expands globs alphabetically).
src="${directory// /_}/$filename"
dst="${f// /_}"
echo mv --no-clobber --no-target-directory -- "$src" "$dst"
done
팁: echo
기능이 만족스러우면 접두사를 제거하세요.
이 스크립트는 공백만 대체합니다. 다른 공백을 바꾸려면 적절하게 조정하십시오. 언급한 대로 이는 에 의해 향상될 수 있지만 extglob
여기서는 멈추겠습니다.