In diesem Artikel findet sich eine Sammlung diverser Terminal-Kommandos, die im Alltag immer wieder nützlich sein können. Falls bereits aus einem dieser Quickies ein eigener Artikel entstand, ist dieser jeweils am Ende der Beschreibung verlinkt.

Dateien und Verzeichnisse

How to Fix App “is damaged and can’t be opened. You should move it to the Trash” Error on Mac

Use the following command to remove the file from the macOS quarantine:

xattr -cr /path/to/bundle.app

The -c flag removes all attributes and -r applies this change recursively to all subfolders.

Delete a file or folder whose name begins with a hyphen (dash/minus)

... by using the command line option "--" to make rm stop parsing command line options, basically like this:

rm -- "- file"
rm -- -\ file
rmdir -- -\ directory

Show Quick Look Preview from the Terminal

qlmanage -p /path/to/file

Aliase finden

mdfind -onlyin PATH 'kMDItemKind == "Alias"'

z.B.:

mdfind -onlyin ~/Documents/ 'kMDItemKind == "Alias"'

Zwei Verzeichnisse miteinander vergleichen

Mit dem   diff-Kommando lassen sich sehr einfach die Inhalte zweier Verzeichnisse rekursiv miteinander vergleichen (beispielsweise zum nachträglichen Verifizieren eines Backups). Durch Entfernen von "r" im folgenden Beispiel wird der Vergleich nicht-rekursiv durchgeführt:

diff -qr ./old/ ./new/

Beispielausgabe:

Only in ./old/: aDeletedFile.txt
Files ./old/anotherFile.txt and ./new/anotherFile.txt differ
Only in ./new/: aNewFile.txt

Alle .svn Metadaten rekursiv löschen

Folgende Anweisung löscht alle .svn Verzeichnisse innerhalb des aktuellen Verzeichnisses und aller Unterverzeichnisse (rekursiv):

find . -regex '.*.svn' -exec rm -rf "{}" \;

Alle .DS_Store Dateien rekursiv löschen

Folgende Anweisung löscht alle .DS_Store Dateien innerhalb des aktuellen Verzeichnisses und aller Unterverzeichnisse (rekursiv):

sudo find ./ -name ".DS_Store" -depth -exec rm {} \;

Um die Dateien auf dem gesamten System zu löschen, ist ./ durch / zu ersetzen.

.DS_Store Dateien auf Netzwerkvolumes verhindern

Um das Erstellen dieser Dateien auf Netzwerkvolumes dauerhaft zu unterbinden, ist folgendes im Terminal einzugeben:

defaults write com.apple.desktopservices DSDontWriteNetworkStores true

Um dies wieder zu deaktivieren, ist folgende Anweisung einzugeben:

defaults delete com.apple.desktopservices DSDontWriteNetworkStores

Daten sicher löschen

⚠️ ACHTUNG: sowohl die Finder-Funktionalität als auch das äquivalente Terminal Kommando wurden in Mac OS X Tiger (Version 10.4) eingeführt, sind aber nur bis OS X Yosemite (Version 10.10) verfügbar. Sie wurden in OS X El Capitan (Version 10.11) entfernt da sie bei der Nutzung auf SSDs konstruktionsbedingt mehr schaden als nützen.

Die Funktion "sicher löschen" des Finder Papierkorbs steht auch im Terminal zur Verfügung und zwar über das Kommando   srm:

srm FILE_OR_DIRECTORY
srm -r DIRECTORY_RECURSIVELY

Dabei stehen verschiedene Varianten zur Auswahl, die auch aus dem Disk Utility bekannt sein dürften (zum Löschen von Partitionen):

-n, --nounlink overwrite file, but do not rename or unlink it
-s, --simple only overwrite with a single pass of random data
-m, --medium overwrite the file with 7 US DoD compliant passes (0xF6, 0x00, 0xFF, random, 0x00, 0xFF, random)
-z, --zero after overwriting, zero blocks used by file

Quelle:   srm manpage, siehe auch: srm in der Wikipedia (engl.)

Dateien und Verzeichnisse verstecken

Folgende Anweisung bewirkt, dass die jeweiligen Objekte im Finder nicht mehr sichtbar sind, ohne diese umbennen zu müssen (nur auf HFS+ Volumes):

chflags hidden FILE_OR_DIRECTORY

Folgendes Kommando bewirkt genau das Gegenteil:

chflags nohidden FILE_OR_DIRECTORY

Siehe auch: Dateien und Ordner verstecken und schützen hier auf Macwrench

.deb Archive entpacken

Die Installationsarchive Debian-basierter Linux-Distributionen lassen sich auch unter Mac OS X mit Bordmitteln entpacken. Dazu wird das Kommandozeilenprogramm   ar verwendet, beispielsweise so:

ar vx dateiname.deb

Die eigentlichen Dateien sind im dabei extrahierten Archiv data.tar.gz enthalten, das sich mit jedem handelsüblichen Packprogramm (z.B. The Unarchiver) oder eben auch im Terminal entpacken lässt:

tar xvfz data.tar.gz

Die Dateien control.tar.gz und debian-binary werden zum reinen Extrahieren einzelner Dateie nicht benötigt, sie enthalten lediglich Informationen zur Installation des Paketes (siehe auch: Debian-Paket in der Wikipedia).

extract .pkg installation packages

xar -xvf PATH_TO_PACKAGE
xar -xvf PATH_TO_PACKAGE -C <destination-folder>
pkgutil --expand PATH_TO_PACKAGE <destination-folder>

for example:

xar -xvf ./InstallAssistant.pkg
pkgutil --expand ./InstallAssistant.pkg /Applications/

show a list of all installed .pkg installation packages

pkgutil --pkgs

or for a specific volume:

pkgutil --pkgs --volume PATH_TO_VOLUME

for example:

pkgutil --pkgs --volume /
pkgutil --pkgs --volume "/Volumes/Macintosh HD/"

Dateilisting mit vollständigen Datumsangaben

Standardmäßig zeit   ls das Dateidatum im Format "Tag Monatsname Stunden:Minuten" an. Um zusätzlich die Sekunden- und Jahresangaben anzuzeigen, ist unter OS X lediglich die Option -T (Großschreibung beachten!) anzuhängen, beispielsweise so:

ls -alT

DVD-RAM oder BD-RE mit best. UDF Version formatieren

die für DVD-RAM geeignete Version ist (v.a. aus Performancegründen, siehe hier und hier) 2.01:

newfs_udf -v "DISCNAME" -r 2.01 /dev/diskX

Für blu-rays (BD-RE) sollte Version 2.5 oder 2.6 verwendet werden:

newfs_udf -v "DISCNAME" -r 2.5 /dev/diskX

Vor dem Formatieren ist die disc zu Deaktivieren was entweder über das Festplatten-Dienstprogramm (Disk Utility) oder mit Hilfe der folgenden Terminal-Anweisung erfolgen kann:

discutil unmountDisk /dev/diskX

diskX ist hierbei durch den jeweils korrekten Wert zu ersetzen, der sich ebenfalls im Festplatten-Dienstprogramm (Disk Utility) oder mit Hilfe der folgenden Terminal-Anweisung ermitteln lässt:

diskutil list

Überprüfen lässt sich das dann mit dem UDF Media Reader

Permanently change the time style of the ls command

... e.g. to include the year as well by using this command:

alias ls='ls --time-style=long-iso'

Valid time styles are:

- [posix-]full-iso
- [posix-]long-iso
- [posix-]iso
- [posix-]locale
- +FORMAT (e.g., +%H:%M) for a 'date'-style format

Administration

Using the builtin Apache web server

In macOS Sierra (Version 10.12) Apple removed the graphical user interface to control the builtin Apache Web Server from the Sharing Preference Pane. The software however is still there and can be used and controlled via the macOS Terminal.

In order to manually start, stop and reatart the builtin web server you can use use the apachectl command:

sudo apachectl start
sudo apachectl stop
sudo apachectl restart
sudo apachectl graceful

To automatically start Apache on boot you can use this command:

sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist

You can revert this using this command:

sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist 

The document root folder is by default located at this path:

/Library/WebServer/Documents/

The configuration files are located here:

/etc/apache2

Important Note: I highly recommend adding all additional configuration such as virtual hosts to a separate configuration file and just add an additional include directive at the end of the main configuration file /etc/apache2/httpd.conf.

From time to time - particularly during major macOS updates - the macOS installer tends to revert all changes to the httpd.conf by reinstalling its default version. So if you follow the advice from above you won't lose your changes to this file, but only have to readd the missing import directive.

Install Rosetta 2 manually

If you need Rosetta to execute a command line utility for intel and don't get the installation dialog to install Rosetta 2, you might as well use one of the following terminal commands to achieve the same thing (installing Rosetta that is, not showing the dialog):

/usr/sbin/softwareupdate --install-rosetta

or this one, which skips the interactive license prompt:

/usr/sbin/softwareupdate --install-rosetta --agree-to-license

Reload Quicklook PLugins

Sometimes, e.g. after uninstalling an app with a Quicklook plugin - the list of available plugins is not being updated and macOS still tries to use the uninstalled plugin to present a certain file type. In order for another plugin to take over you have to reload the list of available plugins by resetting the QuickLook daemon. That's the terminal command to do just that:

 qlmanage -r

Disable/Enable Spotlight Indexing

to disable spotlight indexing altogether - e.g. to determine whether this is the reason for an unusually high CPU load, run the following terminal command:

sudo mdutil -a -i off

You may have to force-kill a hanging mds_store process via the Activity Monitor app for it to finish properly.

Take the opportuniyt to add those volumes and folders to the blacklist which you would like to be excluded from indexing before enabling it again.

Run the following command to enable the indexing:

sudo mdutil -a -i on

Force re-indexing of your system volume

first stop the spotlight indexer (see above), then run this command to purge the spotlight index and thereby forcing spotlight to rebuild it:

sudo rm -rf /System/Volumes/Data/.Spotlight-V100/*

Then start the indexer again (see above)

Delete APFS Snapshots to be able to add partitions to an APFS-formatted drive

if you cannot add any physical partitions to your APFS-formatted drive chances are that there are snapshots preventing you from doing that. To solve this problem you can easily list and delete them using these terminal commands:

tmutil listlocalsnapshots /Volumes/$mountpoint
tmutil thinlocalsnapshots /Volumes/$mountpoint 9999

where the number in the second command specifies the number of snapshots which ought to be deleted

Display a month calendar in the terminal

... by using these commands:

 cal
 cal 2023
 cal 4 2023

Check out the command's man page for more options

Aktuelle Arbeitsspeicher-Belegung prüfen

Durch die Eingabe vom vm_stat kann eine detaillierte Übersich der derzeitigen Arbeitsspeicherauslastung angezeigt werden. Zum errechnen der jeweiligen Größe in *byte ist der entsprechende Wert mit der "page size" zu multiplizieren und durch die jeweilige Potenz von 1024 zu teilen:

vm_stat

liefert beispielsweise:

Mach Virtual Memory Statistics: (page size of 4096 bytes)
Pages free:                        1005031.
Pages active:                       389132.
Pages inactive:                     182756.
Pages speculative:                  219753.
Pages wired down:                   298729.
"Translation faults":            831704131.
Pages copy-on-write:              21865968.
Pages zero filled:               402761914.
Pages reactivated:                 1065664.
Pageins:                           4099764.
Pageouts:                           699567.
Object cache: 181 hits of 1789806 lookups (0% hit rate)

389132 * 4096 / (1024^3) ≅ 1,4844 GB

Siehe auch:

Ungenutzten Arbeitsspeicher freigeben

Mit   purge kann derzeit ungenutzter, aber von Programmen noch reservierter Speicher wieder freigegeben werden:

purge

Startzeit von Prozessen ermitteln

Die folgende Anweisung bewirkt die Ausgabe der aktuell laufenden Prozesse inklusive deren Start-Uhrzeit:

ps -ef

Locating app bundles by their bundle identifier

To ascertain an app's bundle identifier use this command:

mdls /path/to/bundle.app  | grep kMDItemCF

for example

mdls /System/Applications/Calculator.app  | grep kMDItemCF

this will yield something like this:

kMDItemCFBundleIdentifier          = "com.apple.calculator"

In order to locate all locations of such an app bundle use this command:

mdfind kMDItemCFBundleIdentifier = "bundleidentifier"

for example

mdfind kMDItemCFBundleIdentifier = "com.apple.calculator"

which will print out a list of all paths where such a bundle is to be found, like so:

/System/Applications/Calculator.app

PowerPC Applikationen finden

Mit Hilfe des foldenden Terminal-Kommandos lassen sich installierte PowerPC Anwendungen ausfindig machen. Das ist insbesondere vor einem Update auf OSX Lion hilfreich, da diese Anwendungen dann nicht mehr laufen werden (die PowerPC-Unterstützung via Rosetta wurde bekanntlich mit 10.7 entfernt):

system_profiler SPApplicationsDataType

In der dadurch erzeugten Liste lassen sich anhand des Attributs "Kind" PowerPC-Anwendungen identifizieren. Für eine Schnellsuche (ob überhaupt PowerPC Anwendungen existieren) genügt folgender Aufruf:

system_profiler SPApplicationsDataType | grep PowerPC

Siehe auch:   system_profiler manpage, System Profiler in der Wikipedia (engl.)

32-Bit Applikationen finden

Die folgende Terminal-Anweisung ermittelt alle auf dem lokalen System vorhandenen 32bit Applikationen und Programme:

mdfind "kMDItemExecutableArchitectures == '*i386*' && kMDItemExecutableArchitectures != '*x86*'"

und so kann man die Suche auf ein best. Verzeichnis einschränken:

mdfind "kMDItemExecutableArchitectures == '*i386*' && kMDItemExecutableArchitectures != '*x86*'" | grep "/Applications/"

Alternativ kann dies auch über das Programm "Systeminformationen" ermittelt werden, und zwar über "Software" > "Programme" in der linken Spalte. In der oben rechts angezeigten Tabelle existiert dazu eine Spalte "64-Bit (Intel)".

CPU-Typ (32/64 Bit) ermitteln

Einige anweisungen liefern hier falsche Werte, beispielsweise "sysctl hw.cputype" oder "arch" auf einem 2018er Mac Mini (der bekanntlich 64bit ist, hier jedoch als x386 erscheint). Daher müssen ggf. mehrere durchprobiert werden, um den korrekten Wert zu ermitteln:

getconf LONG_BIT
uname -m
sysctl hw.cpu64bit_capable
sysctl hw.cputype
arch

Benutzer remote ausloggen

Hin und wieder kommt es auch unter Mac OS vor, dass die Oberfläche spinnt, keine Benutzeriennahmen annimmt oder der Finder komplett blockiert. Dazu muss man nicht notwendigerweise das komplette System zwangsweise ausschalten (via 4Sek. Powerbutton) sondern es genügt oftmals, entweder den Finder bzw. das Dock zu killen oder den jeweiligen Benutzer zwangsweise abzumelden. Damit werden dann allerdings auch die gestarteten Anwendungen – die ja alle als Kindprozesse von   loginwindow laufen – ebenfalls beendet, so dass nicht gespeicherte Daten unwiderbringlich verloren gehen.

Um die Benutzersitzung also zwangsweise zu beenden, sind folgende Schritte notwendig:

Mit folgendem Kommando die Prozessnummer der entsprechenden loginwindow-Instanz herausfinden (sollte am Benutzer zu erkennen sein):

ps -A -j | grep loginwindow

Mit   kill den Prozess beenden, z.B.:

sudo kill 123

Hinweis: der Prozess /System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow console ist die eigene SSH Session.

Software-Updates nur herunterladen

Vor Mac OS X Snow Leopard (10.6) bot die Software-Update Applikation die Möglichkeit, Updates nur herunterzuladen ohne diese gleich zu installieren. In 10.6 fiel diese Option weg, lässt sich jedoch im Terminal weiterhin mit Hilfe des folgenden Kommandos ausführen:

softwareupdate -d -a

Die heruntergeladenen Installationspakete sind anschließend in folgendem Verzeichnis zu finden:

/Library/Updates/

Weitere Informationen dazu gibt es in der manpage zu   softwareupdate

Bluetooth-Assistent deaktivieren

Um das automatische Starten des Bluetooth-Assistenten zu deaktvieren, wenn beispielsweise beim Aufwachen aus dem Ruhezustand gerade keine Tastatur und/oder Maus aktiv ist, können folgende Anweisugnen im Terminal verwendet werden:

sudo defaults write /Library/Preferences/com.apple.Bluetooth BluetoothAutoSeekKeyboard '0'
sudo defaults write /Library/Preferences/com.apple.Bluetooth BluetoothAutoSeekPointingDevice '0'

Sprache im Anmeldebildschirm ändern

Mit Hilfe der folgenden Terminal-Anweisung kann die Systemsprache geändert werden:

sudo languagesetup

Siehe auch: support.apple.com

Eine App vorübergehend in einer bestimmten Sprache starten

Um eine einzelne App vorübergehend in einer anderen Sprache als der aktuellen Systemsprache zu starten, kann folgende Terminal-Anweisung verwendet werden. Im folgenden Beispiel ist "AppName" durch den Namen des App-bundle (.app Endung optional) sowie "LangCode" durch den ISO-Code der jeweiligen Wunschsprache zu ersetzen:

open -a 'AppName' --args -AppleLanguages '(LangCode)'

z.B.:

open -a Calculator.app --args -AppleLanguages '(de-DE)'

Eine App dauerhaft in einer bestimmten Sprache starten

Um eine einzelne App dauerhaft in einer anderen Sprache als der aktuellen Systemsprache zu starten, kann folgende Terminal-Anweisung verwendet werden. Im folgenden Beispiel ist "AppName" durch den Namen der App (bzw. "BunddleIdentifier" durch deren identifier) und "LangCode" durch den ISO-Code der jeweiligen Wunschsprache zu ersetzen:

defaults write -app NameOfApp AppleLanguages -array LangCode
defaults write BundleIdentifier AppleLanguages '("LangCode")'

z.B.:

defaults write -app Calculator AppleLanguages -array fr
defaults write com.apple.iCal AppleLanguages '("en-US")'

Um das wieder rückgäning zu machen, ist folgende Anweisung auszuführen:

defaults delete -app Calculator AppleLanguages

Wie der Bundle Identifier zu ermitteln ist wird hier beschrieben

Laufende Dienste auflisten

Mit folgender Terminal-Anweisung lassen sich alle laufenden Dienste auflisten:

sudo launchctl list

Hiermit lässt sich prüfen, ob ein bestimmter Dienst gerade läuft, z.B. so:

$ sudo launchctl list | grep analyticsd
216	0	com.apple.analyticsd

Nähre Informationen über einen bestimmten Dienst gibt es mit obigem Kommando, wenn man den entsprechenden Identifier hinzufügt:

$ sudo launchctl list com.apple.analyticsd
{
	"EnableTransactions" = true;
	"LimitLoadToSessionType" = "System";
	"MachServices" = {
		"com.apple.analyticsd.managed" = mach-port-object;
		"com.apple.analyticsd" = mach-port-object;
	};
	"Label" = "com.apple.analyticsd";
	"TimeOut" = 30;
	"OnDemand" = true;
	"LastExitStatus" = 0;
	"PID" = 216;
	"Program" = "/System/Library/PrivateFrameworks/CoreAnalytics.framework/Support/analyticsd";
	"ProgramArguments" = (
		"/System/Library/PrivateFrameworks/CoreAnalytics.framework/Support/analyticsd";
	);
};

Beenden lässt sich ein Dienst dann mit folgender Anweisung:

sudo launchctl unload -w &lt;NAME>

Siehe auch: GIST pwnsdx/disable.sh

Mitteilungszentrale (Notification Center) neu starten

Wenn (z.B. während der Entwicklung) ein Today Widget das Notification Center lahmlegt oder man einfach den Neustart einer Today Extension erzwingen will, kann es notwendig werden, dieses einfach neu zu starten - beispielsweise mit Hilfe folgender Terminal-Anweisung:

killall NotificationCenter

Anschließend wird es automatisch neu gestartet, deutlich erkennbar am verzögerten Aufbau der einzelnen Today Extensions.

Mitteilungszentrale (Notification Center) zurücksetzen

Manchmal ist es aber auch notwendig, die komplette Mitteilungszentrale zurückzusetzen - beispielsweise wenn Widgets fehlen oder Widgets von alten, deinstallierten Apps nicht verschwinden wollen. Dazu muss folgende Anweisung ausgeführt werden und anschließend eine erneute Anmeldung erfolgen:

defaults delete com.apple.notificationcenterui; killall NotificationCenter

Anschließend sollte sich die Mitteilungszentrale so präsentieren wie nach einer Neuinstallation bzw. dem Anlegen eines neuen Benutzerkontos.

macOS Upgrade-Hinweis im Systemupdater ausblenden

Um beispielsweise den Upgrade-Hinweis auf macOS Catalina in Mojave auszublenden, ist folgende Terminal-Anweisung auszuführen:

 sudo softwareupdate --ignore "macOS Catalina"

Nach der nächsten Updatesuche sollte dann der Hinweis verschwinden. Um das Upgrade wieder einzublenden, ist folgende Anweisung im Terminal auszuführen:

 sudo softwareupdate --reset-ignored "macOS Catalina"

Dark mode für einzelne Anwendungen deaktivieren

Anwendungen, die den Dark Mode (noch) nicht fehlerfrei unterstützen, können mit folgender Anweisung dazu gebracht werden, immer im Light Mode zu laufen:

defaults write BUNDLE_IDENTIFIER NSRequiresAquaSystemAppearance -bool yes

z.B. für Reeder 3:

defaults write com.reederapp.rkit2.mac NSRequiresAquaSystemAppearance -bool yes

zum Rückgängingmachen dient diese Anweisung:

defaults delete com.reederapp.rkit2.mac NSRequiresAquaSystemAppearance

macOS Content Caching - Speicherort

Über macOS Content Caching gespeicherte Daten sind üblicherweise an folgendem Ort zu finden:

/Library/Application Support/Apple/AssetCache/Data

Hierbei ist zu beachten, dass es mehrere Caches im Netzwerk geben kann und eine best. Datein auf jedem dieser "content caching peers" zu finden sein kann.

Einen externen Bluetooth-Adapter verwenden

Um (beispielsweise bei älteren Macs oder zur Verbesserung der Reichweite/Verbindungsqualität) standardmäßig nicht den eingebauten sondern einen externen USB-Adapter zu verwenden, ist folgende Terminal-Anweisung zu verwenden:

sudo nvram bluetoothHostControllerSwitchBehavior=always

Das genaue Gegenteil (also immer den internen Adapter zu verwenden) erreicht man mit folgender Anweisung:

sudo nvram bluetoothHostControllerSwitchBehavior=never

Um die standardmäßige Systemeinstellung wiederherzustellen, ist folgende Anweisung zu verwenden:

sudo nvram -d bluetoothHostControllerSwitchBehavior

Diese Änderung bleibt über Neustarts hinweg erhalten. Mit Hilfe des Entwicklungs-Tools "Bluetooth Explorer" (Teil der "Hardware IO Tools for Xcode", für deren Download ein Apple Developer-Account erforderlich ist), kann diese Einstellung auch nur für die aktuelle Sitzung vorgenommen werden.

Bei Verbindungsproblemen kann es evtl. auch helfen, das Bluetooth-Menü bei gedrückten Alt+ Shift Tasten zu öffnen und im Debug Untermenü alle Einstellungen und Geräte zurückzusetzen und anschließend den Mac neu zu starten.

Duplicated VPN entries in the VPN status bar item

The VPN status item has the tendency to show duplicates every now and then which can be a bit confusing. But it usually isn't necessary to reboot the machine or even logout in order to get rid of them. It usually suffices to perform the following steps:

  1. enter the System Preferences pane "Network" and select the VPN adapter
  2. disable "Show VPN status in menu bar"
  3. open the terminal and run this command to restart the menu bar:
    killall -KILL SystemUIServer
    
  4. reenable the menu bar VPN status again and the duplicates should be gone

Create symlinks that work in chrooted environments

Instead of creating symlinks which may not be shown correctly in chrooted environments when being accessed remotely (e.g. via SFTP) you can locally mount one folder into another one to make its contents available at both locations:

mount --bind /path/to/sourcefolder /path/to/destinationfolder

For this to work the destinationfolder has to exist beforehand. See also: RedHat Customer Portal: Bind Mounts and Context-Dependent Path Names

Bundle Identifier eines App-Bundles ermitteln

Der Bundle Identifier einer App ist mit Hilfe folgender Terminal-Anweisung zu ermitteln:

mdls -name kMDItemCFBundleIdentifier /Pfad/zum/App-bundle

z.B.:

mdls -name kMDItemCFBundleIdentifier /System/Applications/Utilities/Terminal.app

macOS Systemversion ermitteln

... und zwar auch von einer anderen als der gerade gestarteten Installation bzw. ohne Zugriff auf deren graphische Benutzeroberfläche. Die Versions- und Buildnummmern steht im Klartext in folgender Datei:

/System/Library/CoreServices/SystemVersion.plist

Und ein Blick in den Info Block des zugehörigen Wikipedia-Artikels - z.B. für macOS Catalina - verrät dann auch ob die vorliegende Version die aktuellste ist.

Direkt auslesen lässt sich beispielsweise die Versionsnummer mit folgender Terminalanweisung:

/usr/libexec/PlistBuddy -c "Print :ProductVersion" /System/Library/CoreServices/SystemVersion.plist

bzw. die Build Version:

/usr/libexec/PlistBuddy -c "Print :ProductBuildVersion" /System/Library/CoreServices/SystemVersion.plist

Der Inhalt dieser Datei sieht beispielsweise so aus:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>ProductBuildVersion</key>
        <string>19H2026</string>
        <key>ProductCopyright</key>
        <string>1983-2022 Apple Inc.</string>
        <key>ProductName</key>
        <string>Mac OS X</string>
        <key>ProductUserVisibleVersion</key>
        <string>10.15.7</string>
        <key>ProductVersion</key>
        <string>10.15.7</string>
        <key>iOSSupportVersion</key>
        <string>13.6</string>
</dict>
</plist>

Full keyboard access

... but like in previous macOS versions such as Mojave. In later macOS versions this option is part of the Accessibility tools and includes an imho pretty ugly, huge focus ring around all UI elements that can be controlled with keyboard shortcuts. Using this option here seems to eliminate this behavior but I'm not sure if there are any ramifications.

defaults write NSGlobalDomain AppleKeyboardUIMode -int 2

The respective option in the "Accessibily" System Preference Pane uses the same value, but seems to set a couple of other flags as well. Hence the missing focus rings I guess...

As usual, this option can be reset by running the following command:

 defaults delete NSGlobalDomain AppleKeyboardUIMode

Prevent Game Center connections

If you're annoyed that the gamed process is constantly bugging you or filling your firewall logs (which seems to have gotten pretty nasty on more recent macOS Versions such as Monterey or Ventura), try this one to prevent gamed from connecting to Apple servers:

launchctl unload -w /System/Library/LaunchAgents/com.apple.gamed.plist

Please note: you will have to disable SIP in order to disable the gamed launch agent.

to reenable it use this command:

launchctl load -w /System/Library/LaunchAgents/com.apple.gamed.plist

On older macOS Versions this might help;

sudo defaults write /System/Library/LaunchAgents/com.apple.gamed Disabled -bool true

or respectively

sudo defaults delete /System/Library/LaunchAgents/com.apple.gamed Disabled

Freigaben starten

Einige Netzwerk-Dienste wie die Bildschirmfreigabe lassen sich auch aus dem Terminal heraus starten:

File Sharing

start AFP with

sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.AppleFileServer.plist

stop it again with

sudo launchctl unload /System/Library/LaunchDaemons/com.apple.AppleFileServer.plist

Please note that AFP support has been dropped in macOS 11.0 (Big Sur) in favor of SMB, so you won't be able to share or access files via AFP on these installations.

for SMB use these commands (SMB requires a user to be selected in the System Preferences pane "Sharing"):

sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.smbd.plist

stop it again with

sudo launchctl unload /System/Library/LaunchDaemons/com.apple.smbd.plist

Screen Sharing

Dienst starten:

sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -activate -configure -access -on -restart -agent -privs -all -allowAccessFor -allUsers

Dienst beenden:

sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -deactivate

Keine Interaktionen zulassen (nur Beobachtungsmodus):

sudo defaults write /var/db/launchd.db/com.apple.launchd/overrides.plist com.apple.screensharing -dict Disabled -bool false

Für weitere Optionen siehe:

sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart --help

Über den Neustart des Mac hinaus aktiv lassen:

sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.screensharing.plist

Remote Login (SSHd)

Dienst starten:

sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist

Dienst beenden:

sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist

Netzwerk

Hostname ändern

sudo scutil --set HostName <hostname>

dabei ist <hostname> durch den gewünschten Hostnamen (ohne domain) zu ersetzen

DNS-Cache leeren

Um nach Änderungen an der DNS-Konfiguration oder der lokalen Namensauflösung in   /etc/hosts kann man mit folgendem Terminal-Kommando den lokalen DNS-Cache leeren:

OS X Version Terminal-Anweisung
bis Mac OS 10.4 (Tiger) sudo lookupd -flushcache
bis Mac OS 10.6 (Snow Leopard) sudo dscacheutil -flushcache
bis OS X 10.8 (Mountain Lion) sudo killall -HUP mDNSResponder
OS X 10.9 (Mavericks) sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
OS X 10.10 (Yosemite) * bis 10.10.3:
sudo discoveryutil mdnsflushcache; sudo discoveryutil udnsflushcaches
seit 10.10.4:
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
OS X 10.11 (El Capitan) sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
OS X 10.12 (Sierra) sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder; sudo killall mDNSResponderHelper
seit macOS 10.13 (High Sierra) sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder

*) In Version 10.10.0 wurde mDNSResponder durch discoveryd ersetzt, der in Version 10.10.4 wegen anhaltender Probleme wieder entfernt wurde. Somit gleicht das Vorgehen in Version 10.10.4 und neuer wieder dem Vorgehen unter OS X Mavericks.

Alle DNS-Records einer Domain ermitteln

Um alle A-, MX-, SOA- etc. -Records einer Domain zu ermitteln, ist folgende Anweisung im Terminal einzugeben:

dig <HOSTNAME> ANY +nocmd +nostats +noquestion

TXT-Records können mit folgenden Anweidungen ausgelesen werden:

dig -t txt <HOSTNAME>
dig TXT <HOSTNAME>
host -t txt <HOSTNAME>

Geöffnete Ports auflisten

Alle geöffneten, numerischen Ports:

lsof -nP | grep LISTEN

dasselbe mit Dienstnamen statt Portnummern:

lsof | grep LISTEN

einen bestimmten Port prüfen (macOS 10.13 und neuer):

lsof -nP -i4TCP:<PORT> | grep LISTEN

z.B.:

sudo lsof -nP -i4TCP:80 | grep LISTEN

dasselbe unter älteren macOS Versionen:

lsof -nP -iTCP:<PORT> | grep LISTEN
lsof -nP -i:$PORT | grep LISTEN

ggf. ist der Aufruf über   sudo notwedig (z.B. für Ports < 1024)

Beispielausgabe:

$ sudo lsof -nP -i4TCP:80 | grep LISTEN
httpd   46234 root    4u  IPv6 0x43d62c23d1f89bbd      0t0  TCP *:80 (LISTEN)
httpd   46238 _www    4u  IPv6 0x43d62c23d1f89bbd      0t0  TCP *:80 (LISTEN)

AirDrop über alle Netzwerk-Schnittstellen (WiFi und LAN) nutzen

defaults write com.apple.NetworkBrowser BrowseAllInterfaces 1

Änderung rückgängig machen:

defaults write com.apple.NetworkBrowser BrowseAllInterfaces 0

bzw.

defaults delete com.apple.NetworkBrowser BrowseAllInterfaces

How to download a whole a website using wget

wget --mirror --convert-links --adjust-extension --page-requisites --no-parent http://example.org

or alternatively:

wget -mkEpnp http://example.org

see also: here

optionally add a user agent, just in case the server discards requests from non-browsers:

 --user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 15_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1"
 --user-agent="Mozilla/5.0 (compatible; Googlebot/2.1; +http://www. google.com/bot.html)"

see also: here

How to download a file with reduced bandwidth using curl

 curl -O <url> --limit-rate <speed>

For example:

 curl -O http://example.org/path/to/file.zip --limit-rate 1000
 curl -O http://example.org/path/to/file.zip --limit-rate 100K
 curl -O http://example.org/path/to/file.zip --limit-rate 2M

Sicherheit

Auf Sandbox prüfen

Die folgende Anweidung prüft, ob ein App-Bundle in einer Sandbox läuft, ohne dies dazu starten zu müssen:

codesign -d --entitlements - <pfad>

z.B.

codesign -d --entitlements - /Applications/Calculator.app

Beispielausgabe:

Executable=/Applications/Calculator.app/Contents/MacOS/Calculator
??qq?<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<true/>
	<key>com.apple.security.files.user-selected.read-write</key>
	<true/>
	<key>com.apple.security.network.client</key>
	<true/>
	<key>com.apple.security.print</key>
	<true/>
</dict>
</plist>

Sandbox-Informationen anzeigen

Um die Sandbox-Konfiguration (entitlements) aus dem Mac App Store heruntergeladener Apps anzuzeigen, sind folgende Anweisungen im Terminal einzugeben:

Gültigkeit der Codesignatur überprüfen
spctl -a -v /Pfad/zum/Appbundle.app
spctl --assess -vv /Pfad/zum/Appbundle.app
check-signature /Pfad/zum/Appbundle.app
Anzeige diverser Informationen über die App
codesign -d -v /Pfad/zum/Appbundle.app

liefert beispielsweise (Apple Configurator):

Identifier=com.apple.configurator
Format=bundle with Mach-O thin (x86_64)
CodeDirectory v=20100 size=18631 flags=0x200(kill) hashes=923+5 location=embedded
Signature size=4169
Info.plist entries=31
Sealed Resources rules=12 files=158
Internal requirements count=2 size=1228
Alternativ
codesign -v --strict --deep --verbose=2 /Pfad/zum/Appbundle.app
codesign -d --deep --verbose=2 -r- /Pfad/zum/Appbundle.app
Anzeige der XML-entitlements im Klartext
codesign -d --entitlements - /Pfad/zum/Appbundle.app

liefert beispielsweise (Apple Configurator):


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<true/>
	<key>com.apple.security.device.usb</key>
	<true/>
	<key>com.apple.security.files.user-selected.read-write</key>
	<true/>
	<key>com.apple.security.network.client</key>
	<true/>
	<key>com.apple.security.temporary-exception.files.absolute-path.read-only</key>
	<array>
		<string>/Library/Preferences/com.apple.usbmuxd.plist</string>
	</array>
	<key>com.apple.security.temporary-exception.files.absolute-path.read-write</key>
	<array>
		<string>/private/var/db/lockdown/</string>
		<string>/private/tmp/</string>
	</array>
	<key>com.apple.security.temporary-exception.sbpl</key>
	<array>
		<string>(allow file-read-data (regex #".+\.iosdevicebackup$"))</string>
		<string>(allow mach-lookup (global-name #"com.apple.syncservices.SyncServer"))</string>
		<string>(allow network-outbound (literal "/private/var/run/usbmuxd"))</string>
		<string>(allow mach-lookup (global-name-regex #"^com\.apple\.DeviceLink\.AppleMobileBackup\..+"))</string>
		<string>(allow mach-lookup (global-name #"com.apple.storeagent-xpc"))</string>
		<string>(allow file-read-data (regex #".+\.ipsw$"))</string>
		<string>(allow distributed-notification-post)</string>
	</array>
</dict>
</plist>
Siehe auch

Disable SIP temporarily

um SIP (System Integrity Protection) vorübergehend zu deaktivieren, ist folgende Vorgehensweise notwendig:

# Mac von der macOS Recovery-Partition starten und dort über das Menü die Terminal-App starten
# csrutil disable
Weitere Informationen zur Nutzung: csrutil (ohne Parameter) # den Mac erneut neu starten

Hinweis: Unter neueren Versionen von macOS (z.B. Ventura oder Sonoma) ist zumindest bei erstmaliger Verwendung offenbar das sog. "Startup Security Utility" zu verwenden, um den Sicherheitsleven herunter- und anschließend wieder heraufzusetzen. Anschließend scheint csrutil jedoch wieder einwandfrei zu funktionieren, ich konnte es in einem aktuellen Fall zur Reaktivierung von SIP bereits wieder verwenden. Beides im Recovery Mode natürlich.

Hinweis 2: seit macOS Monterey kann bei mehreren vorhandenen macOS Installationen nur für diejenige der Sicherheitslevel geändert werden, von dessen Recovery Partition gestartet wurde. Andernfalls wird der Versuch lediglich mit einer entsprechenden Fehlermeldung quittiert.

  1. Zur Reaktivierung von SIP den Mac erneut von der Recovery-Partition starten und eine Terminal-Sitzung starten
  2. csrutil enable
  3. Mac erneut neu starten

Der aktuelle Status lässt sich wie folgt abfragen:

$ csrutil status
System Integrity Protection status: enabled.

Mehr zu SIP auf apple.com, Wikipedia

Gatekeeper deaktivieren

Seit macOS Sierra ist die Option, unsignierte Programme ohne Warnhinweis starten zu können, aus den Privatsphäre-Systemeinstellungen verschwunden. Um diese Option wieder sichtbar zu machen, genügt folgende Anweisung im Terminal:

sudo spctl --master-disable

Um das wieder rückgängig zu machenm, ist folgende Terminal-Anweisung notwendig:

sudo spctl --master-enable

Reset an App's access permissions

Sometimes the System Settings preference pane "Security & Privacy" to configure macOS' Transparency, Consent, and Control (TCC) Framework goes haywire so you can't change an app's privacy settings. Or you just need to do this from the   Terminal for another reason, for example for scripting, or remote access via ssh.

But there is a way to reset an apps privacy settings by using the command line utility tccutil. You can specify a bundle identifier in order to reset the setting for one specific App only. If you omit this all apps registered for that service will be reset and prompt again the next time they access the service.

tccutil COMMAND SERVICE [BUNDLE_IDENTIFIER]

for example:

tccutil reset All com.apple.Terminal
tccutil reset Accessibility
tccutil reset AddressBook
tccutil reset AppleEvents
tccutil reset Calendar
tccutil reset All

Here are a few examples which services are available in here. You have to keep in mind that some serices, such as "Accessibility", automatically reset the configuration for other services, in this case "Automation". Using the keyword "All" resets all of them in one shot:

  • Accessibility
  • AddressBook
  • AppleEvents
  • Calendar
  • Camera
  • CoreLocationAgent
  • Microphone
  • Photos
  • Reminders
   
You can get a full list of all available services by running this command here:
strings /System/Library/PrivateFrameworks/TCC.framework/TCC | grep kTCCService
In order to use one of these service names with tccutil you have to skip the prefix "kTCCService" - for example "Calendar" instead of "kTCCServiceCalendar"
 

See also: How to fix macOS Accessibility permission when an app can’t be enabled (Macworld)

If you want to add a service for a specific app you will have to resort to third-party tools/scripts, such as tccutil.py, since the builtim macOS command only allows for resetting the services.

Bildbe- und -verarbeitung

SVG in PNG umwandeln

Mit folgender Terminalanweisung lässt sich ohne exta zu installierende Software eine SVG-Grafik in ein PNG rastern:

qlmanage -t -s 1024 -o . source.svg 

Weitere Optionen dieses Werkzeugs sind in der mangape verfügbar:

man qlmanage

Entwicklung

Allgemein

Ungültige Zeichen in einer Textdatei finden (also solche, die nicht zum Encoding passen):

grep -axv '.*' path/to/file.txt

iOS Simulator

Screenshot erstellen

Mit Hilfe der folgenden Anweisung lässt sich ein Screenshot des derzeit vom iOS Simulator angezeigten Bildschirminhaltes anfertigen, der dann im aktuellen Verzeichnis (pwd) abgelegt wird:

xcrun simctl io booted screenshot

Alternativ kann ein Zielpfad angegeben werden:

xcrun simctl io booted screenshot <pfad-zur-zieldatei>

Video aufzeichnen

Mit Hilfe der folgenden Anweisung lassen sich Interaktionen im iOS Simulator als Videodatei aufzeichnen:

xcrun simctl io booted recordVideo <pfad-zur-zieldatei>

alle Simulatoren auflisten

xcrun simctl list

alle Simulatoren zurücksetzen

xcrun simctl erase all

Programme

Apple Mail: View emails in plaintext

On older Mac OS X Versions (Mac OS X Mavericks Version 10.9.x/Apple Mail Version 7.x and earlier afaik) there used to the hidden preference described below to force Apple Mail to show emails in plain text instead of HTML. But this option apparently has been dropped and doesn't work any longer (verified with macOS Catalina Version 10.15.x). It's been filed in Radar back then but has never been fixed by Apple, so I guess they just dropped it intentionally. Please drop me an email if you know another way to achieve the same thing by another means (maybe a plugin or something) on more recent macOS versions.

In order to view all emails in plaintext instead of HTML run this terminal command:

defaults write com.apple.mail PreferPlainText -bool true

Tun this command to disable it again:

defaults delete com.apple.mail PreferPlainText

To view a specific email in its original HTML formatting use the main menu entry "View" -> "Message" -> "Next Alternative"

Firefox Profile-Manager starten

Im Profil-Manager lassen sich weitere Benutzerprofile erstellen und verwalten, allerdings ist dieser mittlerweile recht versteckt:

  1. Firefox beenden, falls gerade gestartet
  2. Terminal öffnen
  3. im Terminal folgende Anweisung ausführen:
    /Applications/Firefox.app/Contents/MacOS/firefox-bin -P
    

Dort kann man dann auch (optional) durch Setzen der entsprechenden Checkbox veranlassen, dass der Profil-Manager bei jedem Start angezeigt wird.

Eine Übersicht aller weiteren Startparameter ist mit dieser Anweisung zu erhalten:

/Applications/Firefox.app/Contents/MacOS/firefox-bin --help

Thunderbird Profile-Manager starten

Analog zu Firefox (siehe oben) funktioniert das natürlich auch bei Thunderbird, allerdings mit einem abweichenden Parameternamen:

/Applications/Thunderbird.app/Contents/MacOS/thunderbird-bin --ProfileManager

Eine Übersicht aller weiteren Startparameter ist mit dieser Anweisung zu erhalten:

/Applications/Thunderbird.app/Contents/MacOS/thunderbird-bin --help

MAMP PRO hidden preferences

... moved to MAMP PRO hidden preferences

Troubleshooting

Schwarzer Desktop-Hintergrund

Wenn der Hintergrund aller Spaces plötzlich schwarz wird und man kein Hintergrundbild mehr auswählen kann, hilft folgende Terminal-Anweisung in der Regel weiter, so dass man sich eine Neuanmeldung bzw. einen Reboot sparen kann:

killall Dock

Sonstiges

System-Icons finden

Mit dem folgenden Kommando lassen sich sämtliche vom System verwendeten .icns Dateien auffinden:

find /System/Library /Library -iname \*.icns -print

Apps vom MAS erneut installieren

Es kommt des öfteren mal vor, dass die Mac App Store App deinstallierte Apps nicht als deinstalliert registriert und sich dann standhaft weigert, solche Apps erneut zu installieren. Es erscheint lediglich ein Hinweis, die App sei bereits installiert.

In diesem Fall sollte folgende Terminal-Anweisung dem App Store wieder auf die Sprünge helfen:

/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user

Doppelte Einträge im "Öffnen mit ..." Finder-Menü beseitigen

Hin und wieder kommt es vor, das Programme im Finder-Kontextmenü "Öffnen mit ..." mehrfach gelistet sind. Um diesen Fehler zu bereinigen, ist folgendes im Terminal einzugeben:

/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -r -domain local -domain user

Anschließend ist der Finder mit folgender Anweisung neu zu starten

killall Finder

Alternativ kann das auch über das Dock-Menü erfolgen, in dem während des Klicks auf den Finder-Eintrag die folgenden Tasten gedrückt werden: <KB>CTRL+ALT</KB>

   
Hinweis: dadurch werden auch die Warnhinweise für aus dem Internet heruntergeladenen Programme zurückgesetzt, so dass beim nächsten Start eines solchen Programms OS X erneut nachfragt, ob man ein aus dem Internet geladenes Programm wirklich öffnen möchte.
 

Aktuellen UNIX Timestamps ermitteln

Aktuelle Uhrzeit in Sekunden:

date +%s

Mit Millisekunden (Achtung: date +%N funktioniert nicht unter macOS!)

php -r 'echo microtime(TRUE);'
python -c 'import time; print(int(time.time() * 1000))'

Datum und Uhrzeit von UNIX Timestamps anzeigen

date -r TIMESTAMP

z.B.:

date -r 1616517572

Ausgabe:

Tue Mar 23 17:39:32 CET 2021

Zugriff auf Dateien/Volumes ermitteln

z.B. um herauszufinden. welche Prozesse gerade auf ein bestimmtes Volume zugreifen und damit das Aushängen/Auswerfen verhindern:

sudo lsof | grep PATH

z.B.

$ sudo lsof|grep "/Volumes/Macintosh HD"
mds         110            root   17r      DIR                1,4       1024         2 /Volumes/Macintosh HD
notifyd     151            root   56r      DIR                1,4       1024         2 /Volumes/Macintosh HD

Daten/Verzeichnisse Auf SIP-Schutz prüfen

Mit folgender Anweisung lässt sich prüfen, ob der Zugriff auf bestimmte Dateien/Verzeichnisse durch SIP (System Integrity Protection) eingeschränkt ist:

ls -lO

In solchen fällen erscheint in der Ausgabe dann "restricted", wie beispielsweise hier:

drwxr-xr-x  6 root  wheel  restricted 192 Jun 26 12:47 VirtualBox

Um solche Dateien löschen zu können, muss zunächst SIP vorübergehend deaktiviert und der Mac neu gestartet werden.

Zufallszahl erzeugen

folgende Anweisung erzeugt eine (ganzzahlige) Zufallszahl (größer 0) mit einem Maximalwert von 10:

echo $(( $RANDOM % 10 ))

dasselbe ohne die 0:

echo $(( ( RANDOM % 10 ) + 1 ))

dasselbe mit Werten zwischen 40 und 49:

r=$(( $RANDOM % 10 + 40 )); echo $r

alternativ unter Verwendung von /dev/random:

grep -m1 -ao '[0-9]' /dev/urandom | sed s/0/10/ | head -n1

alternativ unter Verwendung der $RANDOM Bash-Funktion:

 echo $RANDOM % 10 + 1 | bc

oder wie folgt, mit einer etwas besseren Verteilung der erzeugten Werte:

 while :; do ran=$RANDOM; ((ran < 32760)) && echo $(((ran%10)+1)) && break; done

Merge several PDF documents into one

you can do that with ghostscript, which unfortunately has to be installed first, e.g. via homebrew:

brew install gs

Then you can run this command:

 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=merged.pdf source1.pdf source2.pdf source3.pdf

More at Macwrench

General

App-specific

Siehe auch