-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInspect_Text_Notebook.qmd
More file actions
320 lines (226 loc) · 12.7 KB
/
Copy pathInspect_Text_Notebook.qmd
File metadata and controls
320 lines (226 loc) · 12.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
---
title: "Text (.txt) and Markdown (.md) Files // Fichiers texte (.txt) et Markdown (.md)"
author: "Data Curation Team"
date: "2025-12-18"
format:
html:
toc: true
toc-location: left
code-fold: true
theme: cosmo
bibliography: references.bib
params:
target_dir: "data/Inspect_Text/"
---
## Overview // Aperçu
Text files are the simplest form of documentation. However, they are susceptible to encoding and structural issues that impede interoperability.
//
Les fichiers texte constituent la forme la plus simple de documentation. Ils sont toutefois sujets à des problèmes d'encodage et de structure qui nuisent à leur interopérabilité.
::: {.callout-note title="Curation Goal // Objectif de la curation"}
Ensure universal readability of text documents. Our objective is to validate UTF-8 encoding, identify "invisible" characters (BOM), and normalize line endings to ensure documents remain readable across all operating systems.
//
Garantir la lisibilité universelle des documents texte. Notre objectif est de vérifier l'encodage UTF-8, d'identifier les caractères « invisibles » (BOM) et de normaliser les fins de ligne afin de garantir que les documents restent lisibles sur tous les systèmes d'exploitation.
:::
::: {.callout-warning title="Identifying Risks // Identification des risques"}
Character corruption ("Mojibake") caused by legacy encodings (e.g., Windows-1252) and "link rot" from broken external URLs are the primary threats to the long-term usability of plain text documentation.
//
La corruption des caractères (« Mojibake ») due à des encodages obsolètes (par exemple, Windows-1252) et la « pourriture des liens » résultant d'URL externes inactives constituent les principales menaces pour la pérennité de la documentation en texte brut.
:::
**This notebook evaluates text files on three levels:**
1. **Encoding Validation:** Detect character encoding and ensure compliance with the UTF-8 standard.
2. **Structural Integrity:** Identify Byte Order Marks (BOM) and mixed line endings (CRLF/LF).
3. **Link & Security Scan:** Extract external URLs and scan for accidental PII leaks (e.g., email addresses).
//
**Ce notebook analyse les fichiers texte à trois niveaux :**
1. **Validation de l'encodage :** Détecter l'encodage des caractères et s'assurer de la conformité à la norme UTF-8.
2. **Intégrité structurelle :** Identifier les marqueurs d'ordre des octets (BOM) et les fins de ligne mixtes (CRLF/LF).
3. **Analyse des liens et de la sécurité :** extraire les URL externes et rechercher les fuites accidentelles d'informations personnelles identifiables (par exemple, les adresses e-mail).
------------------------------------------------------------------------
## Setup // Configuration
We use `readr` for encoding detection and `stringr` for link extraction.
//
Nous utilisons `readr` pour la détection des encodages et `stringr` pour l'extraction des liens.
### R Packages // Packages R
The following R packages are required. If you don't have these packages, uncomment this code and run it once in your R console:
//
Les packages R suivants sont requis. Si vous ne disposez pas de ces packages, décommentez ce code et exécutez-le une fois dans votre console R :
```{r}
# install.packages(c("tidyverse", "readr", "rstudioapi", "stringr"))
```
### Load libraries // Charger les bibliothèques
```{r}
#| label: load-libraries
#| message: false
library(tidyverse)
library(readr) # For encoding guessing
library(stringr) # For Regex (Links/Emails)
library(rstudioapi) # For directory selection
```
## Select a target directory // Sélectionnez un répertoire de destination
This block allows for interactive selection of the image directory. If running in a non-interactive environment, it defaults to the path defined in the YAML header.
//
Ce bloc permet de sélectionner de manière interactive le répertoire contenant les images. En cas d'exécution dans un environnement non interactif, le chemin par défaut est celui défini dans l'en-tête YAML.
```{r}
#| label: select-target-dir
# 1. Try to select interactively if in RStudio
if (interactive() && .Platform$OS.type == "windows") {
selected_dir <- rstudioapi::selectDirectory(caption = "Select Excel Directory")
} else {
selected_dir <- NULL
}
# 2. Logic to determine final directory (Interactive vs Parameter)
if (!is.null(selected_dir)) {
target_dir <- selected_dir
} else {
target_dir <- params$target_dir
}
print(paste("Analyzing directory:", target_dir))
```
## Inventory and Inspection // Inventaire et analyse
We scan for .txt, .md, .csv, and .rmd files. The inspection extracts encoding confidence, checks for the hidden BOM, identifies line endings, and scans for PII (Emails).
//
Nous recherchons les fichiers aux extensions .txt, .md, .csv et .rmd. L'analyse évalue la fiabilité de l'encodage, vérifie la présence d'une nomenclature cachée, identifie les fins de ligne et recherche les données à caractère personnel (courriels).
```{r}
#| label: extraction-logic
#| warning: false
#| message: false
message("Generating Text Report...")
text_files <- list.files(
path = target_dir,
pattern = "\\.(txt|md|csv|rmd)$",
recursive = TRUE,
full.names = TRUE,
ignore.case = TRUE
)
# Regex Patterns
url_pattern <- "http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+"
email_pattern <- "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"
report <- purrr::map_dfr(text_files, function(file_path) {
fname <- basename(file_path)
tryCatch({
# 1. BOM Detection (Read raw bytes)
con <- file(file_path, "rb")
bytes <- readBin(con, "raw", n = 4)
close(con)
# Check for UTF-8 BOM (EF BB BF)
has_bom <- identical(bytes[1:3], as.raw(c(0xef, 0xbb, 0xbf)))
# 2. Encoding Guess
guess <- readr::guess_encoding(file_path, n_max = 1000)[1, ]
encoding <- if (!is.na(guess$encoding)) guess$encoding else "Unknown"
confidence <- if (!is.na(guess$confidence)) guess$confidence else 0
# 3. Content Analysis (Read text)
# Read safely with UTF-8 fallback
content_lines <- readLines(file_path, warn = FALSE)
full_text <- paste(content_lines, collapse = "\n")
# 4. Line Ending Detection
# We read raw again to distinguish \r\n vs \n (readLines normalizes them)
raw_text <- readChar(file_path, nchars = 2000, useBytes = TRUE)
eol_type <- "Unknown"
if (grepl("\r\n", raw_text)) {
eol_type <- "Windows (CRLF)"
} else if (grepl("\n", raw_text)) {
eol_type <- "Unix (LF)"
} else if (grepl("\r", raw_text)) {
eol_type <- "Classic Mac (CR)"
}
# 5. Extract Artifacts
urls <- str_extract_all(full_text, url_pattern)[[1]]
emails <- str_extract_all(full_text, email_pattern)[[1]]
example_links <- paste(head(unique(urls), 3), collapse = ", ")
tibble(
FileName = fname,
Encoding = encoding,
Confidence = confidence,
HasBOM = has_bom,
LineEndings = eol_type,
LineCount = length(content_lines),
URL_Count = length(urls),
Email_Count = length(unique(emails)),
Example_Links = substr(example_links, 1, 100),
Status = "Success"
)
}, error = function(e) {
tibble(
FileName = fname, Encoding = NA, Confidence = NA, HasBOM = NA,
LineEndings = NA, LineCount = NA, URL_Count = NA, Email_Count = NA,
Example_Links = NA, Status = paste("Failed:", e$message)
)
})
})
# Display preview
print("--- Text Report Preview ---")
head(report)
```
## Visualization // Visualization
We can visualize the distribution of detected encodings. Ideally, the repository should be 100% UTF-8 (or ASCII). Any "ISO-8859" or "Windows-1252" files are candidates for remediation.
//
Nous pouvons visualiser la répartition des encodages détectés. Idéalement, le référentiel devrait être entièrement au format UTF-8 (ou ASCII). Tout fichier au format « ISO-8859 » ou « Windows-1252 » doit faire l'objet d'une correction.
```{r}
#| label: visual-text
#| fig-cap: "Distribution of File Encodings"
if (nrow(report) > 0) {
ggplot(report %>% filter(Status == "Success"), aes(x = Encoding, fill = Encoding)) +
geom_bar() +
labs(
title = "Text File Encodings",
subtitle = "Archival Standard: UTF-8 / ASCII",
x = "Detected Encoding",
y = "File Count"
) +
theme_minimal() +
theme(legend.position = "none")
}
```
## Save Results // Enregistrer les résultats
```{r}
#| label: save-results
output_dir <- "Results/Inspect_Text"
dir.create(output_dir, recursive = TRUE, showWarnings = FALSE)
output_file <- file.path(output_dir, paste0("Text_Report_", format(Sys.Date(), "%Y%m%d"), ".csv"))
write.csv(report, output_file, row.names = FALSE)
print(paste("Report saved to:", output_file))
```
## Curation Insights // Aperçu de la curation
Use the generated CSV to perform these checks:
- **PII Check (Email_Count \> 0):** Text files (especially READMEs) often contain contact information. Verify if these emails are personal (e.g., gmail.com) or professional.
- **Encoding (Encoding != UTF-8):** Legacy files (Windows-1252) or other encodings may display corrupted characters on the web. It is recommended to convert them to UTF-8 using procedures like `iconv` (see below).
- **BOM (HasBOM = TRUE):** The Byte Order Mark (BOM) is often unnecessary for UTF-8 and can break some scripts (e.g., shebang lines in bash). Curators can remove the BOM if the file is intended for code execution. Confirm with the researcher that these are safe to remove.
//
Utilisez le fichier CSV généré pour effectuer les vérifications suivantes :
- **Vérification des données à caractère personnel (Email_Count > 0) :** Les fichiers texte (en particulier les fichiers README) contiennent souvent des coordonnées. Vérifiez si ces adresses e-mail sont personnelles (par exemple, gmail.com) ou professionnelles.
- **Encodage (Encoding != UTF-8) :** Les fichiers hérités (Windows-1252) ou d'autres encodages peuvent afficher des caractères corrompus sur le Web. Il est recommandé de les convertir en UTF-8 à l'aide de procédures telles que `iconv` (voir ci-dessous).
- **BOM (HasBOM = TRUE) :** La marque d'ordre des octets (BOM) est souvent inutile pour l'UTF-8 et peut perturber certains scripts (par exemple, les lignes shebang dans bash). Les conservateurs peuvent supprimer la BOM si le fichier est destiné à l'exécution de code. Vérifiez auprès du chercheur que leur suppression ne présente aucun risque.
## Additional Tools // Outils supplémentaires
- **iconv:** The standard [command-line tool](https://pubs.opengroup.org/onlinepubs/007904975/functions/iconv.html) for converting text encodings (e.g., iconv -f WINDOWS-1252 -t UTF-8 in.txt \> out.txt).
- **dos2unix:** A [tool](https://linux.die.net/man/1/dos2unix) to normalize line endings (converting Windows CRLF to Unix LF). This may be useful for ensuring scripts run correctly on Linux clusters.
- **Internet Archive Wayback Machine:** Use this [website](https://web.archive.org/) to find live versions of broken URLs.
//
- **iconv :** L'[outil en ligne de commande](https://pubs.opengroup.org/onlinepubs/007904975/functions/iconv.html) standard pour convertir les encodages de texte (par exemple, iconv -f WINDOWS-1252 -t UTF-8 in.txt \> out.txt).
- **dos2unix :** Un [outil](https://linux.die.net/man/1/dos2unix) permettant de normaliser les fins de ligne (en convertissant les CRLF de Windows en LF d'Unix). Cela peut s'avérer utile pour garantir le bon fonctionnement des scripts sur les clusters Linux.
- **Internet Archive Wayback Machine :** utilisez ce [site web](https://web.archive.org/) pour trouver des versions actives d'URL qui ne fonctionnent plus.
## Using the Non-Interactive R Script // Utilisation du script R non interactif
For users who want to run this analysis on a server, in a batch job, or from the command line, here is a pure R script that performs the same process.
Download the **R Script:** [**`Inspect_Text_Script.R`**](Scripts/Inspect_Text_Script.R)
//
Pour les utilisateurs qui souhaitent exécuter cette analyse sur un serveur, dans le cadre d'un traitement par lots ou depuis la ligne de commande, voici un script R pur qui effectue le même processus.
Télécharger le **script R :** [**`Inspect_Text_Script.R`**](Scripts/Inspect_Text_Script.R)
### Example HPC Submission Script // Exemple de script de soumission HPC
`Inspect_Text_submit.sh`
``` bash
#!/bin/bash
#SBATCH --job-name=text_check
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --time=00:15:00
#SBATCH --mem=4G
#SBATCH --output=logs/text_check_%j.log
module load R
# Define target directory
TARGET_DIR="/scratch/user/project_data/docs"
# Prepare folders
mkdir -p Results/Inspect_Text
mkdir -p logs
# Run
echo "Starting Text Inspection on $TARGET_DIR"
Rscript Inspect_Text_Script.R "$TARGET_DIR"
```