확장자를 변경하지 않고 파일 이름의 점을 밑줄로 바꾸십시오.

확장자를 변경하지 않고 파일 이름의 점을 밑줄로 바꾸십시오.

파일 이름의 점을 바꾸고 밑줄로 대체하여 확장자를 변경하지 않고 그대로 두는 데 사용하려는 bash 스크립트가 있습니다(btw, 저는 Centos 6을 사용하고 있습니다). 아래 출력에서 ​​볼 수 있듯이 교체해야 할 점이 있을 때 스크립트가 작동하지만 유일한 점이 확장명인 경우 스크립트는 파일을 무시하는 대신 파일 이름을 바꾸려고 계속 시도합니다. 내가 이 문제를 어떻게 더 잘 처리해야 하는지 지적할 수 있는 사람이 있나요? 도와주셔서 감사합니다.

내 (잘못된) 스크립트:

#!/bin/bash

for THISFILE in *
do
  filename=${THISFILE%\.*}
  extension=${THISFILE##*\.}
  newname=${filename//./_}
  echo "mv $THISFILE ${newname}.${extension}"
  #mv $THISFILE ${newname}.${extension}
done

입력 예:

1.3MN-Pin-Eurotunnel-Stw505.51.024-EGS-130x130.jpg
Wear-Plates.jpg

산출:

mv 1_3MN-Pin-Eurotunnel-Stw505_51_024-EGS1-130x130.jpg 1_3MN-Pin-Eurotunnel-Stw505_51_024-EGS1-130x130.jpg
mv Wear-Plates_jpg.Wear-Plates_jpg Wear-Plates_jpg.Wear-Plates_jpg

답변1

나는 이 프로그램이 당신이 원하는 것을 할 것이라고 믿습니다. 테스트해 본 결과 몇 가지 흥미로운 경우(예: 확장이 전혀 없는 경우)에서 작동합니다.

#!/bin/bash

for fname in *; do
  name="${fname%\.*}"
  extension="${fname#$name}"
  newname="${name//./_}"
  newfname="$newname""$extension"
  if [ "$fname" != "$newfname" ]; then
    echo mv "$fname" "$newfname"
    #mv "$fname" "$newfname"
  fi
done

직면하게 되는 주요 문제는 확장 프로그램이 ##원하는 작업을 수행하지 않는다는 것입니다. 나는 항상 bash의 쉘 매개변수 확장이 일종의 흑마법이라고 생각했습니다. 매뉴얼의 설명은 완전히 명확하지 않으며 확장 기능의 작동 방식에 대한 지원 예제가 부족합니다. 그들은 또한 매우 신비합니다.

sed개인적으로 저는 원하는 방식으로 이름을 조정하는 작은 스크립트를 작성하거나 perl전체 작업을 수행하는 작은 스크립트를 작성합니다. 대답한 다른 사람도 이런 접근 방식을 취했습니다.

제가 지적하고 싶은 또 다른 점은 인용문을 사용한다는 것입니다. 나는 쉘 스크립트로 무엇인가를 할 때마다 사람들에게 인용할 때 매우 조심하라고 상기시킵니다. 쉘 스크립트에서 문제의 가장 큰 원인은 쉘이 해석해서는 안되는 것을 해석한다는 것입니다. 그리고 인용 규칙은 명백하지 않습니다. 나는 이 쉘 스크립트에 인용 문제가 없다고 생각합니다.

답변2

사용합니다 for thisfile in *.*.*(즉, 이름에 두 개 이상의 점이 포함된 루프 파일). 변수를 인용하고 이를 사용하여 --아래와 같이 옵션의 끝을 표시 하십시오.mv -- "$thisfile" "$newname.$extension"

zsh를 사용하세요.

autoload -U zmv
zmv '(*).(*)' '${1//./_}.$2'

답변3

이건 어때:

perl -e '
         @files = grep {-f} glob "*";
         @old_files = @files;
         map {
              s!(.*)\.!$1/!;
              s!\.!_!g;
              s!/!.!
             } @files;
         rename $old_files[$_] => $files[$_] for (0..$#files)
        '

면책 조항: 먼저 가상 디렉터리에서 시도해 보세요. 아직 테스트하지 않았습니다!

답변4

이 버전을 사용하면 오른쪽부터 시작하여 유지하려는 포인트 수를 명시적으로 선택할 수 있습니다.

또한 점 이외의 문자를 대체 및/또는 제거하며 대체 문자는 -밑줄이 아니지만 쉽게 변경할 수 있습니다.

#!/bin/sh
# Rename files by replacing Unix-unfriendly characters.

usage () {
    cat <<EOF
usage: $0 [OPTIONS] [--] [FILE [FILE...]]
Rename files by replacing Unix-unfriendly characters.

Options:
 -p N              preserve last N dots in filename, or keep all
                   dots if N < 0 (default: 1)
       --help      show this help and exit
EOF
}

error () {
    printf "%s\n" "$1" 1>&2
}

delete_chars="()[]{}*?!^~%\\\<>&\$#|'\`\""
replace_chars=" _.,;-"

unixify_string () (
    printf '%s\n' "$1" \
        | tr -d "$delete_chars" \
        | tr -s "$replace_chars" - \
        | to_lower \
        | sed 's/^-\(.\)/\1/; s/\(.\)-$/\1/'
)

to_lower () {
    sed 's/.*/\L&/'
}

split () (
    # split '.x.x.x.x'  0 -> '/x.x.x.x.x
    # split '.x.x.x.x'  1 -> '/x.x.x.x/x
    # split '.x.x.x.x'  2 -> '/x.x.x/x/x
    # split '.x.x.x.x' -1 -> '/x/x/x/x/x
    nf=$(printf '%s\n' "$1" | tr -d -C . | wc -c)
    if [ $2 -lt 0 ]; then
        keep=0
    else
        keep=$((nf-$2))
    fi
    IFS=. i=0 out= sep=
    for part in $1; do
        out="$out$sep$part"
        if [ -z "$out" -o $i -ge $keep ]; then
            sep=/
        else
            sep=.
        fi
        i=$(($i+1))
    done
    printf '%s\n' "$out"
)

unixify () (
    IFS=/ out= sep=
    for part in $(split "$1" $2); do
        out="$out$sep$(unixify_string "$part")"
        sep=.
    done
    printf '%s\n' "$out"
)

rename_maybe () (
    dir="$(dirname "$1")"
    name="$(basename "$1")"
    newname="$(unixify "$name" $2)"
    if [ "$newname" != "$name" ]; then
        mv -i "$dir/$name" "$dir/$newname"
    fi
)

# command line arguments

short_opts=p:
long_opts=help

args="$(LC_ALL=C getopt -n "$0" -s sh -o $short_opts -l $long_opts -- "$@")"
if [ $? -eq 0 ]; then
    eval set -- "$args"
else
    exit 1
fi

p=
while [ $# -gt 0 ]; do
    case "$1" in
        --help)
            usage; exit 0 ;;
        -p)
            p="$2"; shift
            if ! [ "$p" -eq "$p" ] 2> /dev/null; then
                error "$0: option requires integer argument -- 'p'"
                exit 1
            fi ;;
        --)
            shift; break ;;
        -*)
            error "$0: illegal option -- '$1'"
            exit 1 ;;
        *)
            break
    esac
    shift
done

# defaults
p=${p:-1}

# echo p=$p
# echo "$@"
# echo n=$#
# exit

if [ $# -lt 1 ]; then
    error "$0: required non-option argument missing"
    exit 1
fi

for file in "$@"; do
    rename_maybe "$file" $p
done

관련 정보