Fuga spazi bianchi quando si utilizza apici inversi
-
05-10-2019 - |
Domanda
Ho avuto un giro di ricerca, e dal mio punto di vista utilizzando apici inversi è l'unico modo in cui posso risolvere questo problema. Sto cercando di chiamare il comando mdls
da Perl per ogni file in una directory per trovare della scorsa volta accede. Il problema che sto avendo è che nei nomi dei file che ho da find
Ho spazi escape che bash, ovviamente, non piace. C'è un modo semplice per sfuggire tutto lo spazio bianco nei miei nomi di file prima di passarli a mdls
. Ti prego perdonami se questa è una domanda ovvia. Sono abbastanza nuovo per Perl.
my $top_dir = '/Volumes/hydrogen/FLAC';
sub wanted { # Learn about sub routines
if ($File::Find::name) {
my $curr_file_path = $File::Find::name. "\n";
`mdls $curr_file_path`;
print $_;
}
}
find(\&wanted, $top_dir);
Soluzione
Se sei sicuro i nomi dei file non contengono a capo (o CR o LF), quindi praticamente tutte le shell Unix accettare backslash citando, e Perl ha la quotemeta
funzione per applicarlo.
my $curr_file_path = quotemeta($File::Find::name);
my $time = `mdls $curr_file_path`;
Purtroppo, questo non funziona per i nomi dei file con a capo, perché le maniglie di shell un backslash seguito da un ritorno a capo eliminando sia caratteri invece che solo la barra rovesciata. Quindi, per essere davvero sicuro, l'uso String :: shellquote :
use String::ShellQuote;
...
my $curr_file_path = shell_quote($File::Find::name);
my $time = `mdls $curr_file_path`;
che dovrebbe funzionare su nomi di file che contengono nulla, tranne un carattere NUL, che davvero non dovrebbe usare nei nomi dei file.
Entrambe queste soluzioni sono solo gusci in stile Unix. Se siete su Windows, corretta guscio citando è molto più complicato.
Altri suggerimenti
Se si vogliono semplicemente "tempo di accesso ultima" in termini di dell'OS ora dell'ultimo accesso, mdls
è lo strumento sbagliato. Utilizzare stat
di perl. Se si desidera ora dell'ultimo accesso in termini di Mac applicazione registrata (ad esempio, una canzone di Quicktime o iTunes) allora mdls
è potenzialmente lo strumento giusto. (Si potrebbe anche usare osascript per interrogare l'applicazione Mac direttamente ...)
I backtick sono per catturare il ritorno del testo. Dal momento che si sta utilizzando mdls, assumo l'acquisizione e l'analisi del testo è ancora a venire.
Quindi ci sono diversi metodi:
-
Utilizza il modulo elenco di sistema e la citazione non è necessario ( se tu non si preoccupano il testo di ritorno);
-
String :: shellquote per sfuggire il nome del file prima di inviarlo a sh;
-
Crea la stringa e racchiudono tra virgolette singole prima di inviare a inviare alla shell. Questo è più difficile di quanto sembri perché i file con i nomi di singoli apici sconfigge le vostre citazioni! Ad esempio,
sam's song.mp4
è un nome di file legale, ma se vi circondano con virgolette singole si ottiene'sam's song.mp4'
che non è quello che volevi dire ... -
Usa
open
per aprire un tubo per l'uscita del processo figlio in questo modo:open my $fh, '-|', "mdls", "$curr_file" or die "$!";
Esempio di stringa :: shellquote:
use strict; use warnings;
use String::ShellQuote;
use File::Find;
my $top_dir = '/Users/andrew/music/iTunes/iTunes Music/Music';
sub wanted {
if ($File::Find::name) {
my $curr_file = "$File::Find::name";
my $rtr;
return if -d;
my $exec="mdls ".shell_quote($curr_file);
$rtr=`$exec`;
print "$rtr\n\n";
}
}
find(\&wanted, $top_dir);
Esempio di tubo:
use strict; use warnings;
use String::ShellQuote;
use File::Find;
my $top_dir = '/Users/andrew/music/iTunes/iTunes Music/Music';
sub wanted {
if ($File::Find::name) {
my $curr_file = "$File::Find::name";
my $rtr;
return if -d;
open my $fh, '-|', "mdls", "$curr_file" or die "$!";
{ local $/; $rtr=<$fh>; }
close $fh or die "$!";
print "$rtr\n\n";
}
}
find(\&wanted, $top_dir);
Se si desidera solo per trovare l'ultimo tempo di accesso, c'è qualche strano motivo Mac non si utilizza stat? Quando sarebbe peggio di kMDItemLastUsedDate
?
my $last_access = ( stat($file) )[8];
Sembra kMDItemLastUsedDate
Non è sempre aggiornato per l'ultima volta di accesso. Se si lavora con un file attraverso il terminale (ad esempio cat
, more
), kMDItemLastUsedDate
non cambia, ma il valore che ritorna dal stat
è giusto. touch
sembra fare la cosa giusta in entrambi i casi.
Sembra che tu abbia bisogno stat
per la vera risposta, ma mdls
se siete alla ricerca per l'accesso attraverso le applicazioni.
È possibile ignorare il guscio esprimendo il comando come un elenco, in combinazione con capture()
da IPC :: System :: Simple :
use IPC::System::Simple qw(capture);
my $output = capture('mdls', $curr_file_path);
Quota il nome della variabile all'interno delle backticks:
`mdls "$curr_file_path"`;
`mdls '$curr_file_path'`;