공백이 포함된 디렉토리 이름 일괄 변경

공백이 포함된 디렉토리 이름 일괄 변경

공백(각 파일 이름에 여러 개)이 포함된 파일과 디렉터리가 여러 개 있고 이를 제거하려고 합니다. 나는 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

Perl 버전이 필요합니다 rename. 당신이 사용하는 것 같습니다 rename.ui:

실행하는 경우:

당신은:

$ file -- "$(type -p rename)"
...ELF 64-bit

당신은 rename.ui.

당신이 가지고 있다면:

$ file -- "$(type -p rename)"
.../rename: Perl script text executable

이것은 Perl의 이름 변경입니다.

에 대한 자세한 설명을 확인해보세요.진주의rename:

독립형 다운로드 또는 복사하여 붙여넣기rename

답변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여기서는 멈추겠습니다.

관련 정보