접미사를 추가하기 위해 파일 이름 바꾸기


13

새 작업 파일 이름이 이전 파일 이름과 같지만 원본 파일의 줄 수에 해당하는 접미사를 포함하여 현재 작업 디렉토리의 모든 파일 이름을 바꾸는 명령이 필요합니다 (예 : 파일 f에 10이있는 경우) 그런 다음 이름을 f_10)으로 바꿔야합니다 .

다음은 작동하지 않는 시도입니다.

 linenum=$(wc -l); find * -type f | grep -v sh | rename 's/^/ec/'*

당신은 그 대답을 할 수 있습니다! (기존의 답변에 새로운 것을 추가한다면-그렇지 않은 것처럼 보입니다)
Volker Siegel

답변:


13

어때요?

for f in *; do mv "$f" "$f"_$(wc -l < "$f"); done

예를 들면 다음과 같습니다.

$ wc -l *
 10 file1
 40 file2
100 file3
$ ls
file1_10  file2_40  file3_100

확장을 유지하려면 (있는 경우)이를 대신 사용하십시오.

for f in *; do 
    ext=""; 
    [[ $f =~ \. ]] && ext="."${f#*.}; 
    mv "$f" "${f%%.*}"_$(wc -l < "$f")$ext; 
done

감사합니다 terdon! 이 명령 줄은 작업을 수행하는 것처럼 보이지만 어떻게 점 (.)을 (_)으로 변경할 수 있습니까? 또한 스크립트가 폴더 안에 있으므로 이름도 바뀌므로 스크립트 이름이 변경되기 때문에 스크립트를 한 번만 실행할 수 있습니다.
Martin Yeboah 2016 년

@MartinYeboah에 대한 업데이트 된 답변을 참조하십시오 _. 스크립트는 어떤 스크립트입니까? 그것은 명령 줄에서 실행되어야하며 스크립트가 필요하지 않습니다. 일부 파일 만 일치 시키 in *려면 예를 들어 in *txt또는로 변경하십시오 .
terdon

고마워;) 나는 명령 줄에서 실행되어야한다는 것을 완전히 잊었다. :)
Martin Yeboah

나는 wc -l < $fgrep 대신 이해하기가 더 쉬울 것이라고 생각 합니다 (아마도 수행하는 것이 좋지만 확인하지 않았습니다).
musiKk 2016 년

@ musiKk 예,하지만 다른 답변이을 사용 wc하고 있기 때문에 다른 접근법을 보여주고 싶었습니다. 하지만 괜찮아요.
terdon

10

이 하나의 라이너를 사용해보십시오.

find . -maxdepth 1 -type f -exec bash -c 'mv -i "$1" "$1.$(wc -l <"$1")"' _ {} \;
  • 현재 작업 디렉토리에있는 모든 파일을 찾을 수 있습니다 ( find . -maxdepth 1 -type f).

  • 그런 다음 찾은 파일에 대해 쉘 인스턴스를 실행하여 줄 수를 추가하기 위해 파일 이름을 바꿉니다.

예 :

$ ls
bar.txt spam.txt foo.txt

$ find . -maxdepth 1 -type f -exec bash -c 'mv -i "$1" "$1.$(wc -l <"$1")"' _ {} \;

$ ls
bar.txt.12 foo.txt.24 spam.txt.7

6

다음을 사용하여 확장 (존재하는 경우)을 유지하는 다른 방법 rename:

for f in *; do rename -n "s/([^.]+)(\.?.*)/\$1_$(< "$f" wc -l)\$2/" "$f"; done

결과가 예상 한 경우 -n옵션을 제거하십시오 .

for f in *; do rename "s/([^.]+)(\.?.*)/\$1_$(< "$f" wc -l)\$2/" "$f"; done

rename위대한 =) +1
AB

1
abcd에서 실패하지 않습니까? 두 번째 캡처 그룹을로 변경하십시오 (\.?[^\.]+).
ps95

@ prakharsingh95 그러나 사실 (\.?[^\.]+)두 번째 점까지만 일치하고 연속적인 점이있는 파일 이름과 일치하거나 점에 관계없이 끝나는 파일 이름과 일치하지 않기 때문에 문제가되지 않습니다. 쉬운 해결책은 아니지만 유일한 방법은 두 가지 대체를하는 것 같습니다.
kos

@ kos 당신이 맞습니다. 어떻습니까 ([^ \.] +). *? ([^ \.] + $) 최적에 대해 잘 모르겠습니다. 일 바이올린 : regex101.com/r/rQ9lX1/1
ps95

1
@ prakharsingh95 당신은 탈출하고 싶지 않아 . 문자 클래스 안에서 .
terdon

5

사용 find:

find . -maxdepth 1 -type f -print0 | while read -d $'\0' f; do mv "$f" "$f"_$(grep -c . "$f"); done

% wc -l *
  3 doit
  5 foo

% find . -maxdepth 1 -type f -print0 | while read -d $'\0' f; do mv "$f" "$f"_$(grep -c . "$f"); done

% wc -l *                         
  3 doit_3
  5 foo_5

-name "*"? 시험에서 남은? ;)
kos

1
@kos Old 습관 : \
AB

3

로 재미와 솔루션을 웃음 rename. 평가 rename된 임의의 문자열을 받아들이는 Perl 도구 이므로 모든 종류의 shenanigan을 수행 할 수 있습니다. 작동하는 것으로 보이는 솔루션은 다음과 같습니다.

rename 's/.*/open(my $f, "<", $_);my $c=()=<$f>;$_."_".$c/e' *

재미있는 아이디어 +1
AB

2

스크립트는 단일 점 및 확장명 (file.txt), 다중 점 및 확장명 (file.1.txt), 연속 점 (file..foobar.txt) 및 파일 이름의 점 (파일 또는 파일..).

스크립트

#!/bin/bash
# Author: Serg Kolo
# Date:  June 25,2015
# Description: script to rename files to file_numlines
# written for http://askubuntu.com/q/640430/295286

# Where are the files ?
WORKINGDIR=/home/xieerqi/substitutions
# Where do you want them to go ?
OUTPUTDIR=/home/xieerqi/substitutions/output

for file in $WORKINGDIR/* ;do 
    FLAG=0
    EXT=$(printf "%s" "$file" | awk -F'.' '{printf "%s",$NF }' )  # extension, last field of dot-separated string
    # EXT="${file##*.}" # Helio's advice is to use parameter expansion, but I dont know how to use it
    if [ -z $EXT ]; then # we have a dot at the end case file. or something
        # so we gotta change extension and filename
        EXT=""
        FILENAME=$(printf "%s" "$file" | awk -F '/' '{ print $NF}' )
        # set flag for deciding how to rename
        FLAG=1
    else
        FILENAME=$( printf "%s" "$file" | awk -F '/' -v var=$EXT '{gsub("."var,"");print $NF}'   ) # filename, without path, lst in
    fi

    NUMLINES=$(wc -l "$file" | awk '{print $1}') # line count

    if [ $FLAG -eq 0 ];then
         echo "$file" renamed as "$OUTPUTDIR"/"$FILENAME"_"$NUMLINES"."$EXT"
        # cp "$file" "$OUTPUTDIR"/"$FILENAME"_"$NUMLINES"."$EXT" # uncomment when necessary
    else
        echo "$file" renamed as "$OUTPUTDIR"/"$FILENAME"_"$NUMLINES""$EXT"
        # cp "$file" "$OUTPUTDIR"/"$FILENAME"_"$NUMLINES""$EXT" # uncomment when necessary
    fi

    #printf "\n"

done

실제 스크립트

$./renamer.sh                                                                                                           
/home/xieerqi/substitutions/file. renamed as /home/xieerqi/substitutions/output/file._0
/home/xieerqi/substitutions/file.. renamed as /home/xieerqi/substitutions/output/file.._0
/home/xieerqi/substitutions/file.1.jpg renamed as /home/xieerqi/substitutions/output/file.1_3.jpg
/home/xieerqi/substitutions/file.1.test.jpg renamed as /home/xieerqi/substitutions/output/file.1.test_3.jpg
/home/xieerqi/substitutions/file.1.test.txt renamed as /home/xieerqi/substitutions/output/file.1.test_2.txt
/home/xieerqi/substitutions/file.1.txt renamed as /home/xieerqi/substitutions/output/file.1_2.txt
/home/xieerqi/substitutions/file.2.jpg renamed as /home/xieerqi/substitutions/output/file.2_3.jpg
/home/xieerqi/substitutions/file.2.test.jpg renamed as /home/xieerqi/substitutions/output/file.2.test_3.jpg
/home/xieerqi/substitutions/file.2.test.txt renamed as /home/xieerqi/substitutions/output/file.2.test_2.txt
/home/xieerqi/substitutions/file.2.txt renamed as /home/xieerqi/substitutions/output/file.2_2.txt
/home/xieerqi/substitutions/foo..bar.txt renamed as /home/xieerqi/substitutions/output/foo..bar_4.txt

파일에는 줄이 없습니다. 그리고 file .. 따라서 행 수는 0입니다.

스크립트 및 제안 된 수정 사항을 검토 한 terdon과 Helio에게 특별한 감사


2

채팅에서 @Helio로 개발 한 또 다른 배쉬 방법 :

for file in *
do
    echo "$file"
    [[ -f "$file" ]] || continue
    [[ $file =~ (.*)(\.[^.]+)$ ]]
    cp "$file" "output/${BASH_REMATCH[1]:-$file}_$(wc -l < "$file")${BASH_REMATCH[2]}"
done

기절 한 두 번째 머리 ( (.*)(\.[^.]+)$)가 있는 이상하게 보이는 단정 한 사람은 적절한 확장 ( .foo, not ..) 과만 일치해야합니다 . 확장명이 없으면 BASH_REMATCH배열이 비어 있습니다. filename의 기본값을 ${BASH_REMATCH[1]:-$file}사용하고 확장명을 그대로 사용하면 이를 활용할 수 있습니다 .

terdon과 Helio가find 제안한대로 도트 파일을 처리하기 위해을 사용할 수 있습니다 .

find -maxdepth 1 -type f -printf '%P\0' | 
while IFS= read -r -d '' file
do
    [[ $file =~ (.*)(\.[^.]+)$ ]]
    cp "$file" "output/${BASH_REMATCH[1]:-$file}_$(wc -l < "$file")${BASH_REMATCH[2]}"
done

+1 : 명령에 대한 설명을 할 수 없습니다. ;-)
Helio
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.