Se você tiver o GNU awk
versão 4 ou posterior instalado, ele tem a capacidade de carregar módulos externos que fornecem funcionalidade não presente no padrão awk ou mesmo% de awk
aprimorada pelo GNU. Ele vem com um conjunto de módulos, incluindo um chamado filefuncs
. O módulo filefuncs
inclui um wrapper awk
para a função stat
do sistema, que pode ser usada para obter informações sobre arquivos (incluindo se eles existem ou não).
O script awk
a seguir carrega o módulo filefuncs
, lê cada linha de entrada, verifica a quinta coluna para decidir qual caminho será pré-pendurado em cada nome de arquivo de entrada e verifica se o arquivo existe. Em caso afirmativo, imprime o caminho completo e o nome do arquivo para stdout. Se isso não acontecer, imprime uma mensagem de aviso para stderr.
A matriz associativa paths
(AKA um "hash" ou "array com hash") e o caminho pré-pendido padrão são meus melhores palpites sobre o que você pretende. Ajuste conforme necessário. Ele corresponde aos dados em suas amostras fornecidas (até mesmo o erro óbvio com a mídia - > / Volumes / Logic), não o que você disse em um dos seus comentários. Se o seu comentário estiver correto, o código pode ser simplificado.
#!/usr/bin/awk -f
# this will only work with GNU awk >= version 4.0
@load "filefuncs"
BEGIN {
FS=OFS="|";
paths["default"] = "/Users/spazek/Pictures/Fotos Library.photoslibrary/Masters/";
paths["Logic"] = "/Volumes/Logic/";
paths["Media"] = "/Volumes/Logic/";
paths["macOS"] = "/";
}
{ if ($5 in paths) {
filename = paths[$5] $1;
} else { # $5 not known in paths array, use a default
filename = paths["default"] $1;
}
# try to stat the file. get the return code in variable 'rc' and error
# string (if any) in 'error'.
rc=stat(filename,fstat);
error=ERRNO; # oddly, ERRNO is a string, not a number.
if (rc == -1) { # return code of -1 is "No such file or directory"
# print warning to stdout and skip to next input line
print filename ": " error > "/dev/stderr"
next;
};
# filename exists, do something with filename.
print filename, $2, $3, $4, $5;
}
Salvar como, por exemplo ./exists.awk
, torne-o executável com chmod +x
(o mesmo que você faria com um shell script) e execute-o assim:
./exists.awk /Users/spazek/Desktop/filelist1.txt
ou canalize o sqlite3 diretamente para ele:
sqlite3 -separator $'|' /Users/spazek/Desktop/xsystx/systphotos.db \
'select RKMaster.imagePath, RKMaster.name, RKMaster.uuid, RKMaster.fileIsReference, ( select RKVolume.name from RKVolume where RKVolume.modelId = RKMaster.volumeId) from RKMaster' \
| ./exists.awk
Eu não sei qual versão do awk
vem com o Mac OS atualmente. Eu suspeito que é provavelmente um BSD awk
ou uma versão antiga do GNU awk
de um tempo antes de a Free Software Foundation mudar para a licença GPLv3 (é por isso que os Macs estão presos no antigo bash
v3 bash
versão 4 - não é porque a Apple não pode atualizar o bash, é porque eles não serão . Use brew se você precisar de uma versão posterior do GNU bash
ou awk
).
De qualquer forma, se você não tem o GNU awk > = v4.0 instalado, você pode fazer o mesmo com qualquer versão de perl
.
O script perl
a seguir não usa nenhum módulo ou recurso perl não padrão e nem precisa usar a função perl
integrada do stat()
, porque o perl tem operadores semelhantes aos do sh
para testar se existe um arquivo. Usaremos o operador -e
aqui, que testa a existência de um arquivo, igual ao de sh
:
#!/usr/bin/perl
use strict;
# declare %paths hash
my %paths = (
"default" => "/Users/spazek/Pictures/Fotos Library.photoslibrary/Masters/",
"Media" => "/Volumes/Logic/",
"Logic" => "/Volumes/Logic/",
"macOS" => "/",
);
# main loop, read in each line of input and process it.
while(<>) {
chomp; # strip trailing linefeed from end-of-line
my $filename=''; # declare $filename to belong to this scope
# split input on "|" characters
my ($path,$name,$id,$reference,$diskname) = split /\|/;
if (defined($paths{$diskname})) {
$filename = $paths{$diskname} . $path;
} else { # diskname not known in %paths hash, use a default
$filename = paths{"default"} . $path;
}
if (! -e $filename) {
# print warning to stderr and skip to next input line
warn "$filename: No such file or directory\n";
next;
};
# filename exists, do something with filename.
print join('|', $filename, $id, $reference, $diskname), "\n";
}
Novamente, salve-o como exists.pl
e torne-o executável com chmod +x
. Executar como:
./exists.pl /Users/spazek/Desktop/filelist1.txt
Qualquer um desses dois scripts será centenas ou milhares de vezes mais rápido que um script de shell usando um while read
ou loop similar.