AppleScript 생성 날짜 기반 폴더 구조 변경 of (do shell script “find

AppleScript가 작성되어 작동하지만 폴더 구조를 만드는 방식을 변경해야합니다. 스크립트는 다음을 수행합니다.

  • 파일이 들어있는 폴더가 선택됩니다 (필자의 경우 사진이됩니다).
  • 그런 다음 생성 된 날짜를 볼 수 있습니다.
  • YYYY를 작성하십시오 (아직 작성되지 않은 경우 폴더 폴더).
  • MM을 만듭니다 (아직 만들지 않은 경우 월 폴더).
  • DD를 작성하십시오 (아직 작성되지 않은 경우 하루 폴더).
  • 그런 다음 사진을이 폴더로 이동하고 다음 사진에 대해 반복하고 완료 될 때까지 반복합니다.

현재 폴더 구조는 다음과 같이 생성됩니다.

2018 "YYYY"
├── 2018-01 "MM"
├── 2018-02

이것은 훌륭하고 설계된대로 작동하지만 폴더의 모양을 바꾸는 데 마음이 바뀌 었습니다. 다음과 같은 구조를 원합니다 (다른 이름 지정 구조와 거의 동일합니다).

2018
├── 001 January
│   ├── 20180101
│   └── 20180102
├── 002 February
│   ├── 20180201
│   └── 20180202
└── 003 March
    ├── 20180301
    └── 20180302

이제 스크립트가 이것을 생성하는 위치를 알아 내려고 노력했지만 실패했습니다. 이제 도움을 받기 위해이 위대한 곳으로 향하고 있습니다.

on run
    SortFiles(POSIX path of (choose folder))
end run

on open (DroppedFolder)
    set DroppedFolder to POSIX path of DroppedFolder
    if text (length of text of DroppedFolder) of DroppedFolder is not "/" then quit
    SortFiles(DroppedFolder)
end open

on SortFiles(SortFolder)
    set AppleScript's text item delimiters to return
    set SortFolderContents to the text items of (do shell script "find '" & SortFolder & "' -type f")
    set FolderMakeList to {}
    repeat with ThisItem in SortFolderContents
        set ThisFile to ThisItem as string
        if ThisFile does not contain "/." then
            tell application "Finder"
                set DateString to text 1 thru 7 of ((creation date of ((POSIX file ThisFile) as alias)) as «class isot» as string)
                set ThisFilesFolder to SortFolder & text 1 thru 4 of DateString & "/"
                set ThisFilesSubfolder to ThisFilesFolder & text 1 thru 7 of DateString & "/"
            end tell
            if ThisFilesFolder is not in FolderMakeList then
                try
                    do shell script ("mkdir '" & ThisFilesFolder & "'")
                end try
                set FolderMakeList to FolderMakeList & ThisFilesFolder
            end if
            if ThisFilesSubfolder is not in FolderMakeList then
                try
                    do shell script ("mkdir '" & ThisFilesSubfolder & "'")
                end try
                set FolderMakeList to FolderMakeList & ThisFilesSubfolder
            end if
            try
                do shell script ("mv '" & ThisFile & "' '" & ThisFilesSubfolder & "'")
            end try
        end if
    end repeat
    return FolderMakeList
end SortFiles



답변

폴더 이름을 지정하는 스크립트 부분은 다음과 같습니다.

set ThisFilesFolder to SortFolder & (do shell script ("date -r " & ThisFilesEpoch & " \"+%b-%Y\"")) & "/"

그러나 스크립트에 대한 간단한 테스트에서 설명 한 폴더 구조를 전혀 작성하지 않은 것처럼 보이므로 셸 명령으로 폴더 이름이 지정된 날짜 문자열을 생성하는 데 놀랍지 않습니다. 이것입니다 :

date -r %time% "+%b-%Y"

여기서 %time%변수에 의해 삽입되며 ThisFilesEpoch파일 (또는 inode)이 작성된 Epoch (1970 년 1 월 1 일) 이후의 시간 (초)을 나타냅니다. 이 쉘 함수 date는이 값 (큰 정수)을 가져 와서 “Unix time”의 값으로 이해하고 토큰이 제공 한 표준 표현을 사용하여 형식을 다시 지정 %b합니다 ( 월) 및 %Y(연도의 네 자리 숫자를 나타냄).

예를 들어,

date -r 1534615274 "+%b-%Y"

보고:

Aug-2018

2018 년 8 월부터 선택한 폴더에있는 파일이 이동되었습니다. 별도의 월별 폴더 나 별도의 연도 폴더를 만들지 않았습니다. "month-year"폴더 만 . 그래서 나는 당신이 완전히 다른 스크립트가 무엇인지 설명 한 것처럼 혼란스러워합니다.

이 스크립트에는 다음과 같은 많은 특성을 가진 여러 가지 특성이 있습니다.

  1. 그것의 게으른 사용법 tryend try;

  2. 문자열의 일부로 사용되는 변수를 둘러싼 리터럴 작은 따옴표 삽입

    do shell script "find '" & SortFolder & "' -type f" 

    대신에

    do shell script "find " & quoted form of SortFolder & " -type f" 
  3. 기괴한 공식 :

    if text (length of text of DroppedFolder) of DroppedFolder is not "/" then...

    이것은 다음과 같이 쓸 수 있습니다

    if text -1 of DroppedFolder is not "/" then...

    또는

    if the last character of DroppedFolder is not "/" then...

    또는

    if DroppedFolder does not end with "/" then...
  4. 그리고do shell script 필요할 때 신중하게 호출하는 명령 도구로 괜찮은를 반복해서 사용 하지만 스크립트가 밀도가 높을 때 스크립트를 채울 때 왜 스크립트가 쉘 / bash 스크립트로 작성되지 않았는지 궁금합니다. 로 시작하십시오. 이 스크립트처럼 쉘 프로세스를 차례로 생성하고 제거하는 오버 헤드 측면에서도 비용이 많이 듭니다.

이러한 스타일 및 기능적 단점과 스크립트가 현재 수행중인 작업과 실제로 수행되는 작업에 대한 혼란을 감안할 때 다시 작성해야한다고 느꼈습니다.

use Finder : application "Finder"
property rootdir : missing value

# The default run handler when run within Script Editor
on run
    using terms from scripting additions
        set root to choose folder
    end using terms from
    set rootdir to Finder's folder root                         -- '
    sortFiles()
end run

# Processes items dropped onto the applet.  The handler expects one or more 
# file references in the form of an alias list, and will process each item in 
# the list in turn.  If an item is not a folder reference, it is ignored.
# For the rest, the contents of each folder is reorganised.
on open droppedItems as list
    repeat with drop in droppedItems
        set rootdir to Finder's item drop
        if rootdir's class = folder then sortFiles()
    end repeat
end open

# Obtains every file in the root directory and all subfolders, moving them
# to new folders nested within the root directory and organised by year, month,
# and date of each file's creation
to sortFiles()
    repeat with f in the list of fileitems()
        set [yyyy, m, dd] to [year, month, day] of (get ¬
            the creation date of Finder's file f)               -- '

        set mmm to text -3 thru -1 of ("00" & (m * 1)) -- e.g. "008"
        set mm to text -2 thru -1 of mmm -- e.g. "08"
        set dd to text -2 thru -1 of ("0" & dd) -- e.g. "01"

        (my newFolderNamed:yyyy inFolder:rootdir)
        (my newFolderNamed:[mmm, space, m] inFolder:result)

        move Finder's file f to my newFolderNamed:[yyyy, mm, dd] ¬
            inFolder:result                                     -- '
    end repeat
end sortFiles

# A handler to house a script object that enumerates the contents of a 
# directory to its full depth
on fileitems()
    script
        property list : every document file in the ¬
            entire contents of the rootdir ¬
            as alias list
    end script
end fileitems

# Creates a new folder with the supplied name in the specified directory, 
# checking first to see whether a folder with that name already exists.  
# In either case, a Finder reference to the folder is returned.
to newFolderNamed:(dirname as text) inFolder:dir
    local dirname, dir

    tell (a reference to folder dirname in the dir) ¬
        to if it exists then return it

    make new folder at the dir with properties {name:dirname}
end newFolderNamed:inFolder:

샘플 파일이 포함 된 테스트 디렉토리에서이 스크립트를 처음 테스트 할 것을 권장합니다. 실제로 최악의 시나리오는 현재 스크립트와 동일하며 실수로 잘못된 디렉토리를 선택하는 상황입니다. 올바른 디렉토리가 선택되었다고 가정하면 최악의 시나리오는 파일이 이동되지 않으므로 일반적으로 매우 안전한 스크립트입니다.

open처리기를 다시 작성하여 여러 항목이 애플릿에 떨어질 수 있도록했습니다. 즉, 예를 들어 두 개의 폴더를 폴더에 놓고 두 폴더의 내용을 재구성 할 수 있습니다. 그러나 나는 이것을 테스트하지 않았습니다. 다시 말하지만, 최악의 시나리오는 아무것도하지 않는다는 것입니다. 이것은 어떤 유형의 파일 참조가 open핸들러에 전달되는지에 대해 잘못 된 경우입니다 ( alias객체 라고 가정 합니다).


답변

% b, % Y 등 변경

열쇠는 다음과 같습니다. http://man7.org/linux/man-pages/man1/date.1.html


답변