nomes de correspondência de padrões rsync

1

Eu gostaria de rsync um monte de arquivos e ignorar qualquer caso, espaços, pontos, traços ou diferenças de sublinhado nos nomes ao combinar o que sincronizar.

Então, como um exemplo extremo "TheFilename.zip" corresponderia a "__THE- --File --- nam-e ...._. zip" (assumindo o tamanho e o tempo correspondentes).

Não consigo pensar em uma maneira de fazer isso.

    
por lbutlr 07.07.2017 / 01:01

2 respostas

1

Esse script provavelmente fará o que você quiser

#!/bin/bash
#
ritem="$1"              # [ user@ ] remotehost : [ / ] remotepath_to_directory
shift

rhost="${ritem/:*}"     # Can be remotehost or user@remotehost
rpath="${ritem/*:}"     # Can be absolute or relative path to a directory

# Get list of files on remote
#
echo "Looking in $rpath on $rhost" >&2
ssh -n "$rhost" find "$rpath" -maxdepth 1 -type f -print0 |
    while IFS= read -r -d $'
375871.sh remotehost:remotepath localpath/*
' rfile do rkey=$(printf "%s" "$rfile" | tr -d '[:space:]_. -' | tr '[:upper:]' '[:lower:]') list[${rkey/*\/}]="$rfile" done # Get list of files from local and copy to remote # ss=0 echo "Considering $*" >&2 for lpath in "$@" do test -f "$lpath" || continue lfile="${lpath/*\/}" lkey=$(printf "%s" "$lfile" | tr -d '[:space:]_. -' | tr '[:upper:]' '[:lower:]') # Do we have a match in the map rfile="${list[$lkey]}" test -z "$rfile" && rfile="$lfile" # Copy across to the remote system echo "Copying $lpath to $rhost:$rpath/$rfile" >&2 rsync --dry-run -av "$lpath" "$rhost":"$rpath/$rfile" || ss=$((ss+1)) done # All done. Exit with the number of failed copies # exit $ss

Exemplo de uso

#!/bin/bash
#
ritem="$1"              # [ user@ ] remotehost : [ / ] remotepath_to_directory
shift

rhost="${ritem/:*}"     # Can be remotehost or user@remotehost
rpath="${ritem/*:}"     # Can be absolute or relative path to a directory

# Get list of files on remote
#
echo "Looking in $rpath on $rhost" >&2
ssh -n "$rhost" find "$rpath" -maxdepth 1 -type f -print0 |
    while IFS= read -r -d $'
375871.sh remotehost:remotepath localpath/*
' rfile do rkey=$(printf "%s" "$rfile" | tr -d '[:space:]_. -' | tr '[:upper:]' '[:lower:]') list[${rkey/*\/}]="$rfile" done # Get list of files from local and copy to remote # ss=0 echo "Considering $*" >&2 for lpath in "$@" do test -f "$lpath" || continue lfile="${lpath/*\/}" lkey=$(printf "%s" "$lfile" | tr -d '[:space:]_. -' | tr '[:upper:]' '[:lower:]') # Do we have a match in the map rfile="${list[$lkey]}" test -z "$rfile" && rfile="$lfile" # Copy across to the remote system echo "Copying $lpath to $rhost:$rpath/$rfile" >&2 rsync --dry-run -av "$lpath" "$rhost":"$rpath/$rfile" || ss=$((ss+1)) done # All done. Exit with the number of failed copies # exit $ss

Remova --dry-run quando estiver satisfeito, pois está funcionando como esperado.

    
por 31.08.2017 / 15:19
0

Como Satō Katsura aponta nos comentários, isso é impossível fazer com rsync fora da caixa. Também é algo que eu acho que rsync não deveria fazer.

Se você estiver copiando um único arquivo , e se esse nome de arquivo estiver disponível na variável name as __THE- - -File---nam-e...._.zip , você poderá remover os caracteres indesejados do nome do arquivo e copiar o arquivo como isso:

ext=${name##*.}
shortname=${name%.$ext}

rsync -a "$name" "user@target:${shortname//[-_ .]}.$ext"

Para name='__THE- - -File---nam-e...._.zip' , $ext será zip e $shortname será __THE- - -File---nam-e...._ .

Se o seu shell não suportar ${parameter//word} , use

rsync -a "$name" "user@target:$(printf '%s' "$shortname" | tr -d '-_ .' ).$ext"

Tanto ${shortname//[-_ .]}.$ext quanto $(printf '%s' "$shortname" | tr -d '-_ .' ).$ext se tornarão THEFilename.zip .

    
por 31.08.2017 / 11:54