diff --git a/DESCRIPTION b/DESCRIPTION index 0a24c93..28a3a94 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: mactheknife Type: Package Title: Various 'macOS'-oriented Tools and Utilities -Version: 0.2.0 -Date: 2019-09-01 +Version: 0.3.0 +Date: 2020-02-11 Authors@R: c( person("Bob", "Rudis", email = "bob@rud.is", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-5670-2640")), @@ -32,4 +32,4 @@ Imports: purrr, anytime, stringi -RoxygenNote: 6.1.1 +RoxygenNote: 7.0.2 diff --git a/NAMESPACE b/NAMESPACE index 0faddad..af7fbe5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,6 +8,7 @@ export(find_dsstore) export(get_app_info) export(kernel_state) export(logger) +export(mdls) export(read_dsstore) export(read_plist) export(resolve_alias) diff --git a/NEWS.md b/NEWS.md index 266543a..970ebbc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,6 @@ +0.3.0 - WIP +* Added `mdls()` + 0.1.0 - WIP * Added `applescript()` function diff --git a/R/mdls.R b/R/mdls.R new file mode 100644 index 0000000..e7ca103 --- /dev/null +++ b/R/mdls.R @@ -0,0 +1,46 @@ +#' Return a data frame of macOS Spotlight Metadata Attributes for the specified paths +#' +#' @param paths paths to files +#' @export +#' @examples +#' mdls( +#' list.files( +#' pathj = file.path(find.package("mactheknife")), +#' recursive = TRUE, +#' full.names = TRUE +#' ) +#' ) +mdls <- function(paths) { + + mdls_cmd <- Sys.which("mdls") + if (mdls_cmd == "") { + stop("mdls command not found. Are you running on macOS?", call.=FALSE) + } + + paths <- path.expand(paths) + + tf <- tempfile(fileext = ".plist") + + lapply(paths, function(.x) { + + if (file.exists(.x)) { + system2(mdls_cmd, args = c("-plist", tf, .x)) + res <- XML::readKeyValueDB(tf) + tolist <- which(lengths(res) > 1) + if (length(tolist)) { + for (idx in tolist) { + res[[idx]] <- I(list(res[[idx]])) + } + } + res <- as.data.frame(res, stringsAsFactors = FALSE) + class(res) <- c("tbl_df", "tbl", "data.frame") + res + } else { + NULL + } + + }) -> out + + dplyr::bind_rows(out) + +} \ No newline at end of file diff --git a/README.Rmd b/README.Rmd index e713556..8c61311 100644 --- a/README.Rmd +++ b/README.Rmd @@ -1,5 +1,7 @@ --- output: rmarkdown::github_document +editor_options: + chunk_output_type: console --- ```{r pkg-knitr-opts, include=FALSE} hrbrpkghelpr::global_opts() @@ -41,6 +43,16 @@ packageVersion("mactheknife") ``` +### `mdls` info + +```{r mdls} +res <- mdls(list.files(here::here("R"), full.names = TRUE)) + +res + +dplyr::glimpse(res) +``` + ### Kernel state vars ```{r ks} @@ -116,7 +128,7 @@ check_sig("/Applications/RSwitch.app") %>% check_notarization("/Applications/RSwitch.app") ``` -## macthekinfe Metrics +## mactheknife Metrics ```{r cloc, echo=FALSE} cloc::cloc_pkg_md() diff --git a/README.md b/README.md index 5e12a3d..806faf0 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ The following functions are implemented: - `kernel_state`: Retrieve kernel state information - `logger`: Log a message to the macOS logging system (searchable from Console.app) + - `mdls`: Return a data frame of macOS Spotlight Metadata Attributes + for the specified paths - `read_dsstore`: Read a .DS\_Store from a file/URL - `read_plist`: Read a macOS property list file - `resolve_alias`: Resolve macOS Alias Files to POSIX path strings @@ -77,14 +79,83 @@ library(mactheknife) # current verison packageVersion("mactheknife") -## [1] '0.2.0' +## [1] '0.3.0' +``` + +### `mdls` info + +``` r +res <- mdls(list.files(here::here("R"), full.names = TRUE)) + +res +## # A tibble: 20 x 27 +## kMDItemContentCrea… kMDItemContentCrea… kMDItemContentModi… kMDItemContentT… kMDItemContentT… kMDItemDateAdded +## +## 1 2018-04-30 00:29:39 2018-04-30 00:00:00 2018-04-30 00:29:39 com.apple.rez-s… 2018-04-30 00:29:39 +## 2 2018-10-09 17:21:09 2018-10-09 00:00:00 2018-10-09 17:23:04 com.apple.rez-s… 2018-10-09 17:21:09 +## 3 2019-09-01 13:37:35 2019-09-01 00:00:00 2019-09-01 14:37:13 com.apple.rez-s… 2019-09-01 13:37:35 +## 4 2019-09-01 13:55:51 2019-09-01 00:00:00 2019-09-01 14:50:36 com.apple.rez-s… 2019-09-01 13:55:51 +## 5 2018-04-30 17:49:23 2018-04-30 00:00:00 2018-04-30 18:05:24 com.apple.rez-s… 2018-04-30 17:49:23 +## 6 2019-10-28 17:03:26 2019-10-28 00:00:00 2019-10-28 17:03:26 com.apple.rez-s… 2019-10-28 17:03:26 +## 7 2018-04-30 00:29:39 2018-04-30 00:00:00 2018-04-30 00:29:39 com.apple.rez-s… 2018-04-30 00:29:39 +## 8 2018-07-25 18:33:44 2018-07-25 00:00:00 2018-07-25 18:46:20 com.apple.rez-s… 2018-07-25 18:33:44 +## 9 2018-04-30 00:29:39 2018-04-30 00:00:00 2019-10-28 17:04:48 com.apple.rez-s… 2018-04-30 00:29:39 +## 10 2020-02-11 19:26:20 2020-02-11 00:00:00 2020-02-11 19:50:05 com.apple.rez-s… 2020-02-11 19:26:20 +## 11 2019-06-02 13:21:57 2019-06-02 00:00:00 2019-06-02 13:21:57 com.apple.rez-s… 2019-06-02 13:21:57 +## 12 2018-04-30 00:29:39 2018-04-30 00:00:00 2018-04-30 00:29:39 com.apple.rez-s… 2018-04-30 00:29:39 +## 13 2018-07-06 16:38:09 2018-07-06 00:00:00 2018-07-06 16:38:09 com.apple.rez-s… 2018-07-06 16:38:09 +## 14 2019-06-02 13:21:57 2019-06-02 00:00:00 2019-06-02 13:21:57 com.apple.rez-s… 2019-06-02 13:21:57 +## 15 2019-10-28 17:04:25 2019-10-28 00:00:00 2019-10-28 17:05:37 com.apple.rez-s… 2019-10-28 17:04:25 +## 16 2018-04-30 00:29:39 2018-04-30 00:00:00 2018-04-30 18:04:05 com.apple.rez-s… 2018-04-30 00:29:39 +## 17 2018-04-30 00:29:39 2018-04-30 00:00:00 2019-09-01 13:55:00 com.apple.rez-s… 2018-04-30 00:29:39 +## 18 2018-04-30 00:29:39 2018-04-30 00:00:00 2018-07-06 16:35:04 com.apple.rez-s… 2018-04-30 00:29:39 +## 19 2018-04-30 00:29:39 2018-04-30 00:00:00 2018-04-30 00:29:39 com.apple.rez-s… 2018-04-30 00:29:39 +## 20 2018-04-30 00:29:39 2018-04-30 00:00:00 2018-07-06 16:33:59 com.apple.rez-s… 2018-04-30 00:29:39 +## # … with 21 more variables: kMDItemDateAdded_Ranking , kMDItemDisplayName , +## # kMDItemFSContentChangeDate , kMDItemFSCreationDate , kMDItemFSCreatorCode , +## # kMDItemFSFinderFlags , kMDItemFSInvisible , kMDItemFSIsExtensionHidden , kMDItemFSLabel , +## # kMDItemFSName , kMDItemFSOwnerGroupID , kMDItemFSOwnerUserID , kMDItemFSSize , +## # kMDItemFSTypeCode , kMDItemInterestingDate_Ranking , kMDItemKind , kMDItemLogicalSize , +## # kMDItemPhysicalSize , X_kMDItemDisplayNameWithExtensions , kMDItemContentModificationDate_Ranking , +## # kMDItemDocumentIdentifier + +dplyr::glimpse(res) +## Observations: 20 +## Variables: 27 +## $ kMDItemContentCreationDate 2018-04-30 00:29:39, 2018-10-09 17:21:09, 2019-09-01 13:37:35, 2019-0… +## $ kMDItemContentCreationDate_Ranking 2018-04-30, 2018-10-09, 2019-09-01, 2019-09-01, 2018-04-30, 2019-10-2… +## $ kMDItemContentModificationDate 2018-04-30 00:29:39, 2018-10-09 17:23:04, 2019-09-01 14:37:13, 2019-0… +## $ kMDItemContentType "com.apple.rez-source", "com.apple.rez-source", "com.apple.rez-source"… +## $ kMDItemContentTypeTree [<"com.apple.rez-source", "public.source-code", "public.data", "publi… +## $ kMDItemDateAdded 2018-04-30 00:29:39, 2018-10-09 17:21:09, 2019-09-01 13:37:35, 2019-0… +## $ kMDItemDateAdded_Ranking 2018-04-30, 2018-10-09, 2019-09-01, 2019-09-01, 2018-04-30, 2019-10-2… +## $ kMDItemDisplayName "airport-scan.R", "applescript.R", "check_sig.R", "check-notary.R", "f… +## $ kMDItemFSContentChangeDate 2018-04-30 00:29:39, 2018-10-09 17:23:04, 2019-09-01 14:37:13, 2019-0… +## $ kMDItemFSCreationDate 2018-04-30 00:29:39, 2018-10-09 17:21:09, 2019-09-01 13:37:35, 2019-0… +## $ kMDItemFSCreatorCode 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +## $ kMDItemFSFinderFlags 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +## $ kMDItemFSInvisible FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, … +## $ kMDItemFSIsExtensionHidden FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, … +## $ kMDItemFSLabel 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +## $ kMDItemFSName "airport-scan.R", "applescript.R", "check_sig.R", "check-notary.R", "f… +## $ kMDItemFSOwnerGroupID 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20… +## $ kMDItemFSOwnerUserID 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, … +## $ kMDItemFSSize 1812, 1593, 842, 1301, 1758, 919, 426, 378, 523, 1018, 246, 1713, 425,… +## $ kMDItemFSTypeCode 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +## $ kMDItemInterestingDate_Ranking 2018-04-30, 2018-10-09, 2019-09-01, 2019-09-01, 2018-04-30, 2019-10-2… +## $ kMDItemKind "Rez Source", "Rez Source", "Visual Studio Code - Insiders document", … +## $ kMDItemLogicalSize 1812, 1593, 842, 1301, 1758, 919, 426, 378, 523, 1018, 246, 1713, 425,… +## $ kMDItemPhysicalSize 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096… +## $ X_kMDItemDisplayNameWithExtensions NA, "applescript.R", "check_sig.R", "check-notary.R", NA, "get-app-inf… +## $ kMDItemContentModificationDate_Ranking NA, 2018-10-09, 2019-09-01, 2019-09-01, NA, 2019-10-28, NA, 2018-07-2… +## $ kMDItemDocumentIdentifier NA, 0, 0, 0, NA, 0, NA, 0, 0, 0, NA, NA, 0, NA, 0, NA, 0, NA, NA, NA ``` ### Kernel state vars ``` r kernel_state() -## # A tibble: 1,321 x 2 +## # A tibble: 1,296 x 2 ## setting value ## ## 1 user.cs_path /usr/bin:/bin:/usr/sbin:/sbin @@ -97,7 +168,7 @@ kernel_state() ## 8 user.line_max 2048 ## 9 user.re_dup_max 255 ## 10 user.posix2_version 200112 -## # … with 1,311 more rows +## # … with 1,286 more rows ``` ### `.DS_Store` example @@ -174,8 +245,9 @@ list.files( lapply(read_dsstore) -> x str(x) -## List of 22 -## $ : chr [1:9] "2018-asx-200" "2019-factset" "2019-ftse250" "2019-germany" ... +## List of 38 +## $ : chr [1:21] "2018-asx-200" "2019-12-heisenberg-year-in-review" "2019-12-radiation" "2019-factset" ... +## $ : chr "data" ## $ : chr [1:4] "figures" "python" "R" "support" ## $ : chr [1:4] "data" "figures" "python" "R" ## $ : chr(0) @@ -187,23 +259,38 @@ str(x) ## $ : chr(0) ## $ : chr(0) ## $ : chr "data" -## $ : chr(0) +## $ : chr "201912" ## $ : chr "data" ## $ : chr [1:2] "data" "working-final_files" ## $ : chr "hars" +## $ : chr(0) +## $ : chr "data" +## $ : chr "R" ## $ : chr "data" ## $ : chr "R" ## $ : chr [1:2] "data" "working-final_files" ## $ : chr "figure-html" ## $ : chr "data" -## $ : chr(0) +## $ : chr "data" +## $ : chr "data" +## $ : chr [1:2] "data" "output" +## $ : chr "R" +## $ : chr [1:5] ".git" ".Rproj.user" "data" "output" ... +## $ : chr "2020-01" +## $ : chr(0) +## $ : chr(0) +## $ : chr [1:2] "data" "orig" +## $ : chr [1:3] "MDR-CA-Slack-HAR-to-CSV.command" "MDR-CA-Slack-HAR-to-CSV.R" "slackhar2csv.Rproj" +## $ : chr [1:36] "2010-11-05-raster.R" "2019-11-01-points.Rmd" "2019-11-02-lines.R" "2019-11-03-polygons.R" ... +## $ : chr [1:3] "GISofThrones" "lake-data" "Shape" +## $ : chr "13" ``` ### “Software Update” History ``` r software_update_history() -## # A tibble: 321 x 6 +## # A tibble: 537 x 6 ## displayName displayVersion date packageIdentifiers processName contentType ## ## 1 XProtectPlistConfigData 2103 2019-06-03 22:18:20 softwareupdated config-data @@ -216,7 +303,7 @@ software_update_history() ## 8 MindNode 6.0.3 2019-06-06 00:50:26 appstoreagent ## 9 Tweetbot 3.3 2019-06-06 00:50:56 appstoreagent ## 10 Microsoft Excel 2019-06-06 00:52:53 installer -## # … with 311 more rows +## # … with 527 more rows ``` ### macOS Version Info (short) @@ -226,7 +313,7 @@ sw_vers() ## # A tibble: 1 x 6 ## ProductName ProductVersion BuildVersion ProductFullName Hardware KernelVersion ## -## 1 Mac OS X 10.15.1 19B86a macOS Catalina (10.15.1) x86_64 19.0.0 +## 1 Mac OS X 10.15.4 19E224g macOS Catalina (10.15.4) x86_64 19.4.0 ``` ### Applescript @@ -290,12 +377,12 @@ check_notarization("/Applications/RSwitch.app") ## 4 origin Developer ID Application: Bob Rudis (CBY22P58G8) ``` -## macthekinfe Metrics +## mactheknife Metrics | Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | | :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: | -| R | 21 | 0.95 | 373 | 0.92 | 119 | 0.75 | 157 | 0.74 | -| Rmd | 1 | 0.05 | 33 | 0.08 | 40 | 0.25 | 54 | 0.26 | +| R | 22 | 0.96 | 399 | 0.92 | 127 | 0.74 | 169 | 0.74 | +| Rmd | 1 | 0.04 | 36 | 0.08 | 44 | 0.26 | 59 | 0.26 | ## Code of Conduct diff --git a/man/mdls.Rd b/man/mdls.Rd new file mode 100644 index 0000000..4b3e706 --- /dev/null +++ b/man/mdls.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mdls.R +\name{mdls} +\alias{mdls} +\title{Return a data frame of macOS Spotlight Metadata Attributes for the specified paths} +\usage{ +mdls(paths) +} +\arguments{ +\item{paths}{paths to files} +} +\description{ +Return a data frame of macOS Spotlight Metadata Attributes for the specified paths +} +\examples{ +mdls( + list.files( + pathj = file.path(find.package("mactheknife")), + recursive = TRUE, + full.names = TRUE + ) +) +} diff --git a/man/software_update_history.Rd b/man/software_update_history.Rd index 5e03933..c8b3a90 100644 --- a/man/software_update_history.Rd +++ b/man/software_update_history.Rd @@ -4,15 +4,16 @@ \alias{software_update_history} \title{Retrieve Software Update history} \usage{ - - software_update_history(su_hist_file = "/Library/Receipts/InstallHistory.plist") +software_update_history( + su_hist_file = "/Library/Receipts/InstallHistory.plist" +) } \arguments{ \item{su_hist_file}{path to "Software Update" history file} } \description{ Modern macOS "Software Update" history is preserved in the -\code{/Library/Receipts/InstallHistory.plist} proeprty list file. The default +\verb{/Library/Receipts/InstallHistory.plist} proeprty list file. The default behaviour is to use this file as a source and parse the property list into a data frame (tibble). The caller can also provide a path to a valid property list "Software Update" history file (i.e. a systems administrator diff --git a/man/src_knowledgeC.Rd b/man/src_knowledgeC.Rd index e3761ba..c715ba4 100644 --- a/man/src_knowledgeC.Rd +++ b/man/src_knowledgeC.Rd @@ -4,8 +4,9 @@ \alias{src_knowledgeC} \title{Source the `knowledgeC.db` on the local system} \usage{ - - src_knowledgeC(knowledgeC_location = "~/Library/Application Support/Knowledge/knowledgeC.db") +src_knowledgeC( + knowledgeC_location = "~/Library/Application Support/Knowledge/knowledgeC.db" +) } \arguments{ \item{knowledgeC_location}{location of the `knowledgeC.db` file (defaults to "`~/Library/Application Support/Knowledge/knowledgeC.db`")}