JSON 콘텐츠를 기반으로 파일 이름 바꾸기

JSON 콘텐츠를 기반으로 파일 이름 바꾸기

두 가지 파일 세트가 있습니다.

file1.txt     file1.json 
file2.txt     file2.json    
file3.txt     file3.json  
...
fileN.txt     fileN.json

JSON 파일에는 다음 형식이 포함되어 있습니다.

{ "ago": "59 sec ago",  "base_time": 1401243133,  "title": "Untitled",  "type": "None",  "retrieval_time": 1401624105,  "id": "qwNAgvYZ" }

해당 파일의 매개변수 값 으로 fileX.txt각 파일의 이름을 바꾸고 싶습니다.titlefileX.json

예를 들어,

rename fileX.txt -> Untitled

다음과 같이 값을 필터링할 수 있습니다.

cat fileX.json | awk -F"\"" '{print $10}'

하지만 기존 파일 이름이 있으면 접미사를 붙여 이름을 바꿔야 합니다.

예 를 들어 기존 Untitled.txt.Untitled-1.txtUntitled-2.txt

답변1

이것은 다음을 사용하는 매우 간단하고 간단한 쉘 스크립트입니다.JSON 파이프라인당신이 원하는 것을하십시오. 멋진 sh/bash 기능을 사용하지 않으며 파일 이름에 대해 최소한의 온전성 검사만 수행합니다.

노트:json보다 훨씬 강력 jsonpipe하지만 jsonpipejson 데이터의 구조에 특별히 관심이 없거나 이해하고 싶지 않고 하나 또는 두 개의 필드를 추출하고/하거나 행을 사용하여 json을 사용하려는 경우 사용하기 더 간단하고 쉽습니다. 지향적인 텍스트 처리 도구(예: awk등)는 데이터 처리를 수행합니다 sed.grep

한 가지 확실한 개선 사항은 printf0으로 채워진 정수 필드를 사용하여 파일 이름을 고정 너비의 번호가 매겨진 이름으로 바꾸는 것입니다. 예를 들어 Untitled-0001.txt원하는 Untitled-1.txt경우 이를 수행하도록 남겨 두겠습니다.

작성된 대로 실제로 파일 이름을 바꾸지는 않습니다. mv명령 만 인쇄합니다.회의사용. 실제로 파일 이름을 바꾸도록 echo각 명령 앞의 를 제거하도록 편집하십시오 .mv

#! /bin/sh

for f in file*.txt ; do
  b=$(basename "$f" .txt)

  # ignore current .txt file if there's no matching .json file
  if [ -e "$b.json" ] ; then
    # extract the title field.
    title=$(jsonpipe < "$b.json" | 
            awk -F'\t' '$1=="/title" {gsub(/\"/,"",$2) ; print $2}')

    if [ -n "$title" ] ; then
      if [ ! -e "$title.txt" ] ; then
        echo mv -v "$f" "$title.txt"
      else
        # are there any other "$title-*.txt" filenames?
        others=$(find . -maxdepth 1 -name "$title-*.txt")
        if [ -z "$others" ] ; then
          echo mv -v "$f" "$title-1.txt"
        else
          # use version-sort to get highest $title- number used.
          highest=$(printf "%s\n" "$others" | sort -V | tail -n 1)
          hnum=$(printf "%s\n" "$highest" | sed -e 's/^.*-// ; s/\.txt$//')
          hnum=$(( highest_num + 1))
          echo mv -v "$f" "$title-$hnum.txt"
        fi
      fi
    fi
  fi
done

사용 예/작동 증명:

$ ls -l
total 8
-rw-rw-r-- 1 cas cas 132 May 19 23:47 file1.json
-rw-rw-r-- 1 cas cas   0 May 20 00:04 file1.txt
-rwxrwxr-x 1 cas cas 797 May 20 00:04 json-rename.sh

$ cat file1.json 
{"ago": "59 sec ago", "base_time": 1401243133, "title": "Untitled",
 "type": "None", "retrieval_time": 1401624105, "id": "qwNAgvYZ"}

$ ./json-rename.sh 
mv -v file1.txt Untitled.txt

$ touch Untitled.txt
$ ./json-rename.sh 
mv -v file1.txt Untitled-1.txt

$ touch Untitled-1.txt
$ ./json-rename.sh 
mv -v file1.txt Untitled-2.txt

$ touch Untitled-999.txt
$ ./json-rename.sh 
mv -v file1.txt Untitled-1000.txt

답변2

for name in file*.txt; do
    json=${name%.txt}.json
    if [ -f "$json" ]; then
        eval "$(
            jq -r --arg name "$name" '[ "mv", "--", $name, .title ] | @sh' "$json"
        )"
    fi
done

이것은 패턴과 일치하는 현재 디렉토리의 모든 이름을 반복합니다 file*.txt. 이러한 각 이름에 대해 json파일 이름 접미사 .txt.json.

생성된 파일 이름이 기존 파일과 일치하는 경우 jqJSON 파일을 구문 분석하는 데 사용됩니다. 현재 파일의 이름을 .title문서에 있는 키의 문자열 값 으로 바꾸는 쉘 명령을 작성합니다 . 쉘은 생성된 명령을 평가하여 파일 이름을 바꿉니다.

JSON 파일의 유효성은 검사되지 않으며 이름 충돌은 처리되지 않습니다.

이름 충돌을 처리하는 가장 쉬운 방법은 GNU coreutils를 사용하고 있는지 확인한 mv다음 해당 --backup옵션을 사용하는 것입니다.

표현식을 jq다음으로 변경합니다.

jq -r --arg name "$name" '[ "mv", "-v", "--backup=numbered", "--", $name, .title ] | @sh' "$json"

GNU를 사용하여 번호가 매겨진 백업을 만든다는 것은 백업 파일 끝에 mv파일 이름 접미사(예 .~1~: , 등)를 추가하는 것을 의미합니다. 또한 수행 중인 작업에 대한 일부 출력을 얻기 위해 여기에 GNU 옵션을 .~2~추가했습니다 .-vmvmv

renamed 'file.txt' -> 'Untitled' (backup: 'Untitled.~2~')

관련 정보