フォルダ内の階層全てのエイリアスを作りたい

Macでフォルダ内の階層全てのエイリアスを作成するアプリもしくは方法をご存じでしょうか?

仕事内容の都合上、OSのバージョンは上げられずにいたのですが、最近Mojaveにしました。

OS High Sierraまでは「AutoCatalog」や「AliasDisk」といったアプリを使って全ファイルのエイリアスを作成してファイル管理に役立ててきましたが、OS Mojaveから使用できなくなり、残念に思っています。

フォルダ内の階層をテキストで書き出すことはできるのですが、エイリアスの方がフォルダ内部の状態がビジュアル的に把握しやすいので、重宝しておりました。

模試ご存じの方がおられたら、ご教示ください。

Mac mini, macOS 10.13

投稿日 2023/02/01 17:34

返信
スレッドに付いたマーク ランキングトップの返信

投稿日 2023/02/02 04:56

私もなんとかできました。

ちょっとコードが複雑でもっと整理できるかもしれませんが、動作確認はできています。

なお、お伺いした目的からAliasフォルダはデスクトップ固定で作成することにしましたので、作成後に所定の場所に移動してください。

参考になれば幸いです。

on run
	
	--ターゲットフォルダの選択
	set tgtfolder to choose folder
	set tgtpath to tgtfolder's POSIX path
	
	--エイリアスフォルダの場所:デスクトップに固定
	set aliasfolder to ((path to desktop folder) as text) & "Alias:"
	set aliaspath to aliasfolder's POSIX path
	
	--フォルダ階層を複製:ここがキモ!
	do shell script "rsync -ar --include \"*/\" --exclude \"*\" " & tgtpath's quoted form & " " & aliaspath's quoted form
	
	tell application "Finder"
		set getfiles to ((folder tgtfolder)'s entire contents)'s files
		repeat with getfile in getfiles
			set parentpath to ((parent of getfile) as alias)'s POSIX path
			set putaliaspath to my replaceText(parentpath, tgtpath, aliaspath) --エイリアスの作成場所
			make new alias at POSIX file putaliaspath to getfile --エイリアスの作成
		end repeat
	end tell
	
end run


on replaceText(theText, serchStr, replaceStr)
	set tmp to AppleScript's text item delimiters
	set AppleScript's text item delimiters to serchStr
	set theList to every text item of theText
	set AppleScript's text item delimiters to replaceStr
	set theText to theList as string
	set AppleScript's text item delimiters to tmp
	return theText
end replaceText

類似の質問

返信: 22
スレッドに付いたマーク ランキングトップの返信

2023/02/02 04:56 tat224 への返信

私もなんとかできました。

ちょっとコードが複雑でもっと整理できるかもしれませんが、動作確認はできています。

なお、お伺いした目的からAliasフォルダはデスクトップ固定で作成することにしましたので、作成後に所定の場所に移動してください。

参考になれば幸いです。

on run
	
	--ターゲットフォルダの選択
	set tgtfolder to choose folder
	set tgtpath to tgtfolder's POSIX path
	
	--エイリアスフォルダの場所:デスクトップに固定
	set aliasfolder to ((path to desktop folder) as text) & "Alias:"
	set aliaspath to aliasfolder's POSIX path
	
	--フォルダ階層を複製:ここがキモ!
	do shell script "rsync -ar --include \"*/\" --exclude \"*\" " & tgtpath's quoted form & " " & aliaspath's quoted form
	
	tell application "Finder"
		set getfiles to ((folder tgtfolder)'s entire contents)'s files
		repeat with getfile in getfiles
			set parentpath to ((parent of getfile) as alias)'s POSIX path
			set putaliaspath to my replaceText(parentpath, tgtpath, aliaspath) --エイリアスの作成場所
			make new alias at POSIX file putaliaspath to getfile --エイリアスの作成
		end repeat
	end tell
	
end run


on replaceText(theText, serchStr, replaceStr)
	set tmp to AppleScript's text item delimiters
	set AppleScript's text item delimiters to serchStr
	set theList to every text item of theText
	set AppleScript's text item delimiters to replaceStr
	set theText to theList as string
	set AppleScript's text item delimiters to tmp
	return theText
end replaceText

2023/02/02 07:37 Pajerow への返信

応急処置でパッケージのゴミファイルを削除するロジックを追加しました。

on run
	
	--ターゲットフォルダの選択
	set tgtfolder to choose folder
	set tgtpath to tgtfolder's POSIX path
	
	--エイリアスフォルダの場所:デスクトップに固定
	set aliasfolder to ((path to desktop folder) as text) & "Alias:"
	set aliaspath to aliasfolder's POSIX path
	
	--フォルダ階層を複製:ここがキモ!
	do shell script "rsync -ar --include \"*/\" --exclude \"*\" " & tgtpath's quoted form & " " & aliaspath's quoted form
	
	--パッケージフォルダ(サイズなし)の削除
	tell application "Finder"
		set getfiles to ((folder aliasfolder)'s entire contents)'s files
		repeat with getfile in getfiles
			if getfile's size is missing value then delete getfile
		end repeat
	end tell
	
	
	tell application "Finder"
		set getfiles to ((folder tgtfolder)'s entire contents)'s files
		repeat with getfile in getfiles
			set parentpath to ((parent of getfile) as alias)'s POSIX path
			set putaliaspath to my replaceText(parentpath, tgtpath, aliaspath) --エイリアスの作成場所
			make new alias at POSIX file putaliaspath to getfile --エイリアスの作成
		end repeat
	end tell
	
end run


on replaceText(theText, serchStr, replaceStr)
	set tmp to AppleScript's text item delimiters
	set AppleScript's text item delimiters to serchStr
	set theList to every text item of theText
	set AppleScript's text item delimiters to replaceStr
	set theText to theList as string
	set AppleScript's text item delimiters to tmp
	return theText
end replaceText

2023/02/02 16:26 Pajerow への返信

度々スレッドを汚しまして、大変申し訳ありません。


誤りを見つけましたので再度修正しました。

on run
	
	--ターゲットフォルダの選択
	set tgtfolder to choose folder
	set tgtpath to tgtfolder's POSIX path
	
	--エイリアスフォルダの場所:デスクトップに固定
	set aliasfolder to ((path to desktop folder) as text) & "Alias:"
	set aliaspath to aliasfolder's POSIX path
	
	--フォルダ階層を複製:ここがキモ!
	do shell script "rsync -ar --include \"*/\" --exclude \"*\" " & tgtpath's quoted form & " " & aliaspath's quoted form
	
	--パッケージフォルダ(サイズなし)の削除
	tell application "Finder" to delete (((folder aliasfolder)'s entire contents)'s files where its size is missing value)
	
	--エイリアスフォルダにターゲットファイルのエイリアスを作成
	tell application "Finder"
		set getfiles to ((folder tgtfolder)'s entire contents)'s files
		repeat with getfile in getfiles as list
			set parentpath to ((parent of getfile) as alias)'s POSIX path
			set putaliaspath to my replaceText(parentpath, tgtpath, aliaspath) --エイリアスの作成場所
			make new alias at (POSIX file putaliaspath) to getfile --エイリアスの作成
		end repeat
	end tell
	
end run


on replaceText(theText, serchStr, replaceStr)
	set tmp to AppleScript's text item delimiters
	set AppleScript's text item delimiters to serchStr
	set theList to every text item of theText
	set AppleScript's text item delimiters to replaceStr
	set theText to theList as string
	set AppleScript's text item delimiters to tmp
	return theText
end replaceText

2023/02/02 03:58 tat224 への返信

ご希望のものとは少し異なりますが、ターミナルでtreeを使うのはどうでしょう?

フォルダーはアイコンでは表示されませんが、フォルダー名がテキストで表示されます。またこれは、元々unixコマンドなのでmacOSバージョンがどう変わろうが使えます(多分)。ただ、macOSに初めから入ってるわけではありませんので、HomebrewをインストールしてからHomebrewのコマンドとしてtreeをインストールし、そこで使うことになります。こう書くとややこしそうですが、慣れればそれほど複雑ではありません(多分、私自身は使ってませんので責任は持てません)。以下記事を紹介しておきます。この中に実際にtreeを使った例も書いてあります。

MacでTreeコマンドを使いディレクトリ構造をテキスト出力する

この記事自体は少し古いですが、以下にHomebrewの記事によればventuraでもtreeは使えるとしてます。

https://formulae.brew.sh/formula/tree

2023/02/03 07:56 Hiro__S への返信

何度も済みません...。パッケージ対応版の問題点を修正しました。今度は多分大丈夫だと思います。


'use strict';

ObjC.import('Cocoa');

var App = Application.currentApplication(); App.includeStandardAdditions = true;

function isPackage(fpath) {
    return $.NSWorkspace.sharedWorkspace.isFilePackageAtPath(fpath);
}

function filtered(dir, files) {
    const pkgs = [];
    for (const f of files) {
        if (isPackage($(dir).stringByAppendingPathComponent(f).js)) {
            pkgs.push(f);
        }
    }
    for (const p of pkgs) {
        files = files.filter(f => $(f).lastPathComponent.js !== '.DS_Store' && !f.startsWith(p + '/'));
    }
    return files;
}

function run() {
    const dir1 = App.chooseFolder({withPrompt:'元フォルダを選択してください'}).toString();
    const dir2 = App.chooseFolder({withPrompt:'先フォルダを選択してください'}).toString();

    const filemanager = $.NSFileManager.defaultManager;
    const files = ObjC.deepUnwrap(filemanager.enumeratorAtPath(dir1).allObjects.sortedArrayUsingSelector('localizedStandardCompare:'));

    for (const f of filtered(dir1, files)) {
        const old_fpath = $(dir1).stringByAppendingPathComponent(f);
        const new_fpath = $(dir2).stringByAppendingPathComponent(f);
        const isdir = Ref();
        if (filemanager.fileExistsAtPathIsDirectory(old_fpath, isdir) && isdir[0] && !isPackage(old_fpath)) {
            const err = $();
            if (! filemanager.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(new_fpath, true, $(), err)) {
                throw new Error(err.localizedDescription.js);
            }
        } else {
            const src = $.NSURL.fileURLWithPath(old_fpath);
            const dst = $.NSURL.fileURLWithPath(new_fpath);
            const err = $();
            const opt = $.NSURLBookmarkCreationSuitableForBookmarkFile;
            const bookmark = src.bookmarkDataWithOptionsIncludingResourceValuesForKeysRelativeToURLError(opt, $(), $(), err);
            if (! err.isNil()) {
                throw new Error(err.localizedDescription.js);
            } else {
                const err = $();
                if (! $.NSURL.writeBookmarkDataToURLOptionsError(bookmark, dst, 0, err)) {
                    throw new Error(err.localizedDescription.js);
                }
            }
        }
    }
}


2023/02/01 19:17 tat224 への返信

突貫工事で簡単なAppleScriptを作成してみました。

以下のコードになります。


ダイアログで選択したフォルダ内の全階層にあるファイルのエイリアスを、最上位フォルダに作成した"Alias"フォルダの中に作成します。

set tgtfolder to choose folder
tell application "Finder"
	set aliasfolder to make new folder at tgtfolder with properties {name:"Alias"}
	set tgtfiles to ((folder tgtfolder)'s entire contents)'s files
	make new alias at aliasfolder to tgtfiles
end tell


Aliasフォルダの上書きなどの対応はしておりませんので、その辺を含めてもっと詳しい方がいらっしゃいますので、その方のコメントをお待ちください。

もちろんご自身で改造なさっても結構です。


※ 不都合やリクエストがありましたらお知らせください。

2023/02/02 04:44 tat224 への返信

JXA (JavaScript for Automation) で作ってみました。動作は Mojave 10.14.6 で確認しました。


作り方

  1. スクリプトエディタを起動し、
  2. 新規ウインドウの左上にある言語セレクタを「JavaScript」にして、
  3. コードをコピペ
  4. スクリプト形式で保存


使い方

  1. スクリプトエディタから実行
  2. ダイアログに従いコピー元フォルダを選択
  3. ダイアログに従いコピー先フォルダを選択


コード

'use strict';

var App = Application.currentApplication(); App.includeStandardAdditions = true;

function run() {
    const dir1 = App.chooseFolder({withPrompt:'元フォルダを選択してください'}).toString();
    const dir2 = App.chooseFolder({withPrompt:'先フォルダを選択してください'}).toString();
    const filemanager = $.NSFileManager.defaultManager;
    const isdir = Ref();
    for (const f of filemanager.enumeratorAtPath(dir1).allObjects.js) {
        const old_fpath = $(dir1).stringByAppendingPathComponent(f);
        const new_fpath = $(dir2).stringByAppendingPathComponent(f);
        if (filemanager.fileExistsAtPathIsDirectory(old_fpath, isdir) && isdir[0]) {
            const err = $();
            if (! filemanager.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(new_fpath, true, $(), err)) {
                throw new Error(err.localizedDescription.js);
            }
        } else {
            const fname = old_fpath.lastPathComponent.js;
            if (! /^\./.test(fname)) {
                const src = $.NSURL.fileURLWithPath(old_fpath);
                const dst = $.NSURL.fileURLWithPath(new_fpath);
                const err = $();
                const bookmark = src.bookmarkDataWithOptionsIncludingResourceValuesForKeysRelativeToURLError(
                    $.NSURLBookmarkCreationSuitableForBookmarkFile,
                    $(),
                    $(),
                    err
                );
                if (! err.isNil()) {
                    throw new Error(err.localizedDescription.js);
                } else {
                    const err = $();
                    if (! $.NSURL.writeBookmarkDataToURLOptionsError(bookmark, dst, 0, err)) {
                        throw new Error(err.localizedDescription.js);
                    }
                }
            }
        }
    }
}


2023/02/02 05:29 tat224 への返信

treeコマンドを使う方法ですが、出力をhtmlファイルにすることもできます。

その他いろいろなオプションがあります。以下の記事に説明があります。

【 tree 】コマンド――ディレクトリをツリー状に表示する

例えば、htmlファイルで出力しておいて、それをサーバに置いておけば、データのディレクトリー構造をいつもsafariなどブラウザで見れるようにできます。テキスト出力をそのままファイルにすると、それを表示したときに、フォントによってはツリー構造が乱れますが、htmlファイルにしておけば避けることができます。

2023/02/02 17:26 tat224 への返信

Pajerow さんのコメントにもありますが、私の貼ったコードもパッケージ (xxx.app、xxx.rtfd、AVCHD 等々) を考慮してません。その点だけご留意ください。


あと、はにさんご提案の、tree コマンドにより HTML ファイルで書き出す方法はとても便利です。簡易カタログとして私も使ってます。同コマンドは導入のハードルがちょっと高めですが、時間があるときにでもトライしてみると良いでしょう。


2023/02/02 02:18 Pajerow への返信

そうなんです。”元のフォルダと同じ階層構造で”です。

具体的にやりたい(やっていた)事は

作業済みのデータを焼いた バックアップ用ブルーレイディスクの

エイリアス(何の物件データがどんな状態で保存されているかが一見して判る)を作成して、

それを共有サーバーに置いてカタログ代わりに使用していたので、それを継続したい。

というものです。

日頃、過去データフォルダ内の構造だけでもサッと見たいという場合がよくるため、

”元のフォルダと同じ階層構造で”が重要になっております。

共有サーバーに作業済みの実データを保存していくとあっという間に容量が一杯になってしまうため

このような若干トリッキーなことをしています。

2023/02/02 07:11 Pajerow への返信

(おことわり)


先に私が提示したスクリプトにおいて、一部不具合が判明しましたので報告します。

--フォルダ階層を複製:ここがキモ!
	do shell script "rsync -ar --include \"*/\" --exclude \"*\" " & tgtpath's quoted form & " " & aliaspath's quoted form
	

このrsyncコマンドで、”パッケージ形式ファイルがフォルダ認識されてエイリアスと同名の0バイトファイルが余分に作成される”ことが判明しました。

パッケージ形式以外のファイルでは問題ありません。


以上、ご留意ください。


詳しい方で回避方法がわかればお教えくださいませ。


2023/02/02 21:57 Hiro__S への返信

パッケージに対応版です。もうちょっと効率的にできるかもしれませんが、とりあえず動くと思います。


'use strict';

ObjC.import('Cocoa');

var App = Application.currentApplication(); App.includeStandardAdditions = true;

function isPackage(fpath) {
    return $.NSWorkspace.sharedWorkspace.isFilePackageAtPath(fpath);
}

function filtered(dir, pkgs, files) {
    for (const f of files) {
        if (isPackage($(dir).stringByAppendingPathComponent(f).js)) {
            pkgs.push(f);
        }
    }
    for (const p of pkgs.filter(x => ! /\//.test(x))) {
        files = files.filter(f => ! f.startsWith(p + '/') && ! f.startsWith('.'));
    }
    return files;
}

function run() {
    const dir1 = App.chooseFolder({withPrompt:'元フォルダを選択してください'}).toString();
    const dir2 = App.chooseFolder({withPrompt:'先フォルダを選択してください'}).toString();

    const filemanager = $.NSFileManager.defaultManager;
    const files = ObjC.deepUnwrap(filemanager.enumeratorAtPath(dir1).allObjects.sortedArrayUsingSelector('localizedStandardCompare:'));
    const pkgs = [];

    for (const f of filtered(dir1, pkgs, files)) {
        const old_fpath = $(dir1).stringByAppendingPathComponent(f);
        const new_fpath = $(dir2).stringByAppendingPathComponent(f);
        const isdir = Ref();
        if (filemanager.fileExistsAtPathIsDirectory(old_fpath, isdir) && isdir[0] && !isPackage(old_fpath)) {
            const err = $();
            if (! filemanager.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(new_fpath, true, $(), err)) {
                throw new Error(err.localizedDescription.js);
            }
        } else {
            const src = $.NSURL.fileURLWithPath(old_fpath);
            const dst = $.NSURL.fileURLWithPath(new_fpath);
            const err = $();
            const opt = $.NSURLBookmarkCreationSuitableForBookmarkFile;
            const bookmark = src.bookmarkDataWithOptionsIncludingResourceValuesForKeysRelativeToURLError(opt, $(), $(), err);
            if (! err.isNil()) {
                throw new Error(err.localizedDescription.js);
            } else {
                const err = $();
                if (! $.NSURL.writeBookmarkDataToURLOptionsError(bookmark, dst, 0, err)) {
                    throw new Error(err.localizedDescription.js);
                }
            }
        }
    }
}


2023/02/02 00:37 Pajerow への返信

Pajerow様

とんでもないスピードで作成して頂き、ありがとうございます。

スクリプト、すごいですね。ちょっと、勉強してみたくなりました。

さて、贅沢を承知で更にお尋ねしたいのですが

下図のように、頂いたスクリプトを(1)に対して走らせると(2)を作成してくれますが、

(3)のように階層(フォルダ)を生かすことは出来るのでしょうか?

よろしくお願い致します。

このスレッドはシステム、またはAppleコミュニティチームによってロックされました。 問題解決の参考になる情報であれば、どの投稿にでも投票いただけます。またコミュニティで他の回答を検索することもできます。

フォルダ内の階層全てのエイリアスを作りたい

Apple サポートコミュニティへようこそ
Apple ユーザ同士でお使いの製品について助け合うフォーラムです。Apple Account を使ってご参加ください。