파일 이름 끝에 날짜가 수정 된 타임 스탬프가있는 여러 파일의 이름을 바꾸시겠습니까?


14

따라서 g.txt와 같은 많은 파일이있는 디렉토리가 있습니다 .g.txt는 마지막으로 2012 년 6 월 20 일에 수정되었습니다.

마지막 수정 날짜가 2012 년 6 월 20 일 끝에 추가 된 모든 파일 (g.txt 등)을 일괄 이름을 바꾸려면 어떻게해야합니까?

답변:


13

빠르고 더러운 Bash one-liner를 사용하여 현재 디렉토리의 모든 (글로브 된) 파일 이름 filename.txtfilename.txt-20120620다음에서

for f in *; do mv -- "$f" "$f-$(stat -c %Y "$f" | date +%Y%m%d)"; done

진취적인 Bash 머저리가 그것을 깨뜨릴 수있는 최첨단 사례를 발견 할 것입니다. :)

분명히 이것은 파일 끝에 이미 날짜처럼 보이는 것이 있는지 확인하는 것과 같은 바람직한 일을하지 않습니다.


2
+1, 좋아 보인다. mv의 첫 번째 인수로 '-'를 사용하여 좀 더 강력하게 만들 수 있습니다. '-'로 시작하는 filenaes로부터 보호
cas

5
어떤 date구현입니까? 내 GNU date는 입력을 처리하지 않는 것 같습니다.
manatwork

RHEL 6의 coreutils 8.4
jgoldschrafe

2
@jgoldschrafe, 코드가 제대로 작동합니까? pastebin.com/nNYubf3A
manatwork

5
좋은 캐치 작업. 내 GNU 날짜 8.13은 stdin에서 읽는 것을 지원하지 않습니다. "-r"(예 : "date + % Y % m % d -r $ f")과 함께 파일의 모드 시간 사용을 지원하므로이 특정 상황에서는 stat가 필요하지 않습니다.
cas

18

다음은 goldschrafe의 단일 라이너 버전입니다.

  • 통계를 사용하지 않습니다
  • 이전 버전의 GNU 날짜에서 작동
  • 파일 이름의 공백에 올바르게 대처하십시오.
  • 대시로 시작하는 파일 이름에도 대응

    for f in *; do mv -- "$f" "$f-$(date -r "$f" +%Y%m%d)"; done


1
환경에 date -r "$f" +%Y%m%d있으면 만들어야합니다. 그렇지 않으면 작동하지 않습니다 POSIXLY_CORRECT. 일반적으로 옵션은 다른 인수보다 우선합니다.
Stéphane Chazelas

이것은 "정답"이어야합니다
invalidusername

물론에 중괄호가 필요하지 않습니다 "${f}".
G-Man은 '복귀 모니카'

그러나 "Ymd-filename"과 같이 앞에 붙인 날짜를 어떻게 만드시겠습니까?
timebandit

2

필수 zsh one-liner (선택적 구성 요소의 일회성로드는 계산하지 않음) :

zmodload zsh/stat
autoload -U zmv
zmv -n '(*)' '$1-$(stat -F %Y%m%d +mtime -- $1)'

우리 statzsh/stat모듈 의 내장 zmv기능 과 파일 이름 바꾸기 기능을 사용합니다. 그리고 여기에 연장 전에 날짜를 두는 여분의 것이 있습니다.

zmv -n '(*)' '$1:r-$(stat -F %Y%m%d +mtime -- $1)${${1:e}:+.$1:e}'

1

이해했듯이 수정 날짜가 무엇인지 미리 알 수 없습니다. 따라서 각 파일에서 가져 와서 출력 형식을 지정하고 파일 이름에 수정 날짜가 포함되도록 각 파일의 이름을 바꾸어야합니다.

이 스크립트를 "modif_date.sh"와 같은 이름으로 저장하여 실행 가능하게 만들 수 있습니다. 대상 디렉토리를 인수로 사용하여 호출합니다.

modif_date.sh txt_collection

여기서 "txt_collection"은 이름을 바꾸려는 모든 파일이있는 디렉토리의 이름입니다.

#!/bin/sh

# Override any locale setting to get known month names
export LC_ALL=c
# First we check for the argument
if [ -z "$1" ]; then
    echo "Usage: $0 directory"
    exit 1
fi

# Here we check if the argument is an absolute or relative path. It works both ways
case "${1}" in
  /*) work_dir=${1};;
  *) work_dir=${PWD}/${1};;
esac

# We need a for loop to treat file by file inside our target directory
for i in *; do
    # If the modification date is in the same year, "ls -l" shows us the timestamp.
    # So in this case we use our current year. 
    test_year=`ls -Ggl "${work_dir}/${i}" | awk '{ print $6 }'`
    case ${test_year} in *:*) 
        modif_year=`date '+%Y'`
        ;;
    *)
        modif_year=${test_year}
        ;;
    esac
    # The month output from "ls -l" is in short names. We convert it to numbers.
    name_month=`ls -Ggl "${work_dir}/${i}" | awk '{ print $4 }'`
    case ${name_month} in
            Jan) num_month=01 ;;
            Feb) num_month=02 ;;
        Mar) num_month=03 ;;
        Apr) num_month=04 ;;
        May) num_month=05 ;;
        Jun) num_month=06 ;;
        Jul) num_month=07 ;;
        Aug) num_month=08 ;;
        Sep) num_month=09 ;;
        Oct) num_month=10 ;;
        Nov) num_month=11 ;;
        Dec) num_month=12 ;;
        *) echo "ERROR!"; exit 1 ;;
    esac
    # Here is the date we will use for each file
    modif_date=`ls -Ggl "${work_dir}/${i}" | awk '{ print $5 }'`${num_month}${modif_year}
    # And finally, here we actually rename each file to include
    # the last modification date as part of the filename.
    mv "${work_dir}/${i}" "${work_dir}/${i}-${modif_date}"
done

1
stat (1) 매뉴얼 페이지를 읽고 스크립트를 약 3/4 줄이는 방법을 찾으십시오. 위의 대부분은 바퀴를 다시 발명합니다. 특히 'stat -c % Y'는 신기원 이후 (1970-01-01 00:00:00) 이후 파일의 수정 시간을 초 단위로 제공합니다. 그런 다음 date (1)의 입력으로 사용하여 필요에 따라 타임 스탬프를 형식화 할 수 있습니다. 예제는 위의 jgoldschrafe의 답변을 참조하십시오.
cas

@CraigSanders 단점은이 스크립트가 다른 stat유틸리티를 갖거나 전혀없는 Linux 이외의 운영 체제에서 작동한다는 것 입니다.
Gilles 'SO- 악한 중지'

출력ls구문 분석하는 것은 신뢰할 수 없습니다 . 일부 유닉스 변형에서는 사용자 및 그룹 이름에 공백이 포함될 수 있으므로 날짜 열의 정렬이 중단됩니다.
Gilles 'SO- 악한 중지'

@giles : true, 그러나 현명한 사람 :-)은 리눅스가 아닌 시스템에 GNU coreutils (및 다른 모든 GNU 도구)를 설치합니다. 좋은 유저 랜드 도구 세트뿐만 아니라 기본 커널에 관계없이 일관된 세트를 얻는 가장 쉬운 방법입니다.
cas

1
(계속) (5) 또 다른 버그 : 그것은 어떤 날짜 / 시간으로 표시한다고 가정 ls 으로 현재 연도에 있어야합니다 날짜와 시간 (보다는 날짜와 연도). 사실이 아닙니다. 지난 6 개월 동안입니다. 이는 전년도에있을 수 있습니다 (예 : 2016 년 9 월 27 일부터 2016 년 12 월 31 일까지는 지난 6 개월 이내). (6) Greg 's Wiki (@Gilles가 이미 인용 한)를 손상 시킬 위험 이 있으므로 줄 바꿈과 공백이 포함 된 파일 이름으로 인해 실패 할 수 있습니다. … (계속)
G-Man, 'Reinstate Monica'라고

0

다음은 CAS의 oneliner의 버전 (goldschrafe의 oneliner 기준)이다는로 확장 멱등 ,

즉, 날짜 시간이 붙은 파일을 접두어로 확장하고 아직 날짜 시간 접두사가없는 파일에 대해서만이를 수행 하도록 확장되었습니다 .

유스 케이스 : 디렉토리에 새 파일을 추가하고 아직없는 파일에 날짜 시간 접 두부를 추가하려는 경우에 유용합니다.

for f in * ; do
  if [[ "$f" != ????-??-??' '??:??:??' - '* ]]; then
    mv -v -- "$f" "$(date -r "$f" +%Y-%m-%d' '%H:%M:%S) - $f" ;
  fi;
done

파일의 타임 스탬프가 나사 및 사진과를있는 경우, 당신은 전나무는 EXIF 데이터로 문제를 해결 할 수 있습니다 : for f in *.jpg ; do jhead -ft "$f" ; done소스 : unix.stackexchange.com/a/290755/9689
그르 Wierzowiecki
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.