Вы не можете разархивировать файл на удаленном сервере с помощью SFTP. Это просто невозможно.
Если у вас есть доступ к серверу через оболочку, вы можете разархивировать файл с помощью оболочки:
sshpass -p $PSWRD ssh User@xxx.xxx.com unzip $zipfilename
Поскольку у вас, похоже, нет доступа к оболочке, то, если у вас нет еще одного доступа (, например, какой-либо веб--панели управления ), вы не сможете разархивировать файл на сервере..
Эта проблема состоит из нескольких частей:
Из имен ваших примеров не совсем ясно, что вы считаете базовой частью имени файла. Разделителем, очевидно, является точка, но в примере, подобном yet.a.different.file.name.foo.bar1-2.baz
, какая точка? Вы упоминаете попытку использовать *.(<->|baz|bar<->.baz)
, которая не будет рассматривать foo
или bar1-2
как расширение. Твик, который позволяет использовать их в качестве расширения, — .(foo|<->|baz|bar<->(|-<->).baz)
. Затем вы можете разбить имя файла $f
следующим образом:
setopt extended_glob
base=${f%%(.(<->|baz|bar<->(|-<->).baz))#}; extensions=${f#$base}
В качестве альтернативы, если приемлемо определить базу как все до и за исключением первого .foo.
, декомпозиция упрощается:
base=${f%*.foo.*}; extensions=${f#$base}
Если вы хотите применить детерминированное преобразование, вы можете просто пересчитывать каждый раз. Например, вы можете получить псевдослучайный результат, взяв MAC-адрес имени с секретным ключом, каждый раз используя один и тот же секретный ключ.
secret=$(openssl rand -hex 32)
for … # Loop over the files as per (3.), set $base and $extensions as per (1.)
new_base=${"$(openssl dgst -sha256 -hmac $secret <<<$base)"[-16,-1]}
(Обратите внимание, что :секретный ключ будет виден другим пользователям, если они запустят ps
во время работы openssl
. Я предполагаю, что это не проблема в вашем случае, но будущие читатели должны остерегаться этого.)
Если вы хотите применить рандомизированное преобразование, вам нужно помнить, чему соответствует каждое основание. Есть два способа сделать это:
Второй метод проще, а первый метод не имеет особых преимуществ, поэтому я покажу только второй метод.
Построить ассоциативный массив , отображающий базы в новые базы.
typeset -A mapping
mapping=()
for … # Loop over the files as per (3.), set $base and $extensions as per (1.)
if ((!$+mapping[$base])); then
mapping[$base]=$(openssl rand -hex 8)
fi
new_base=$mapping[$base]
Zsh поставляется с очень полезным инструментом для переименования файлов :zmv
. Преобразование, которое вы хотите сделать, достаточно сложное, поэтому zmv не делает его тривиальным :как декомпозиция имени файла, так и преобразование требуют дополнительной работы. Даже в вашем случае у zmv есть небольшие преимущества. В частности, zmv выдаст ошибку, если конфликт (крайне маловероятен из-за случайных факторов, если только вы не используете более короткие длины ). Однако из-за сложности преобразования имени использовать zmv неудобно, а простой цикл написать проще.
Вот полный фрагмент со случайными именами.
setopt extended_glob
typeset -A mapping
mapping=()
for f in *.(foo|<->|baz|bar<->(|-<->).baz); do
base=${f%%(.(foo|<->|baz|bar<->(|-<->).baz))#}; extensions=${f#$base}
if ((!$+mapping[$base])); then
mapping[$base]=$(openssl rand -hex 8)
fi
new_base=$mapping[$base]
mv -i -- $f $new_base$extensions
done
Вот полный фрагмент, использующий детерминированные имена для заданного значения $secret
.
setopt extended_glob
secret=$(openssl rand -hex 32)
for f in *.(foo|<->|baz|bar<->(|-<->).baz); do
base=${f%%(.(foo|<->|baz|bar<->(|-<->).baz))#}; extensions=${f#$base}
new_base=${"$(openssl dgst -sha256 -hmac $secret <<<$base)"[-16,-1]}
mv -i -- $f $new_base$extensions
done
А вот один -вкладыш, использующий zmv
для детерминированного случая, первый .foo.
используется для обозначения конца основания. Флаг -w
помогает с разбивкой.
autoload zmv
secret=$(openssl rand -hex 32)
zmv -w '*.foo.*' '${"$(openssl dgst -sha256 -hmac $secret <<<$1)"[-16,-1]}.foo.$2'
Использование zmv в рандомизированном случае сложнее, потому что нам нужно сохранять информацию от одного шага преобразования к другому. Мы можем просто упаковать некоторый код в подстановку команд zmv … '$(…; if …; then mapping[$base]=…; …)'
, потому что назначение mapping
будет внутри подоболочки подстановки команд и, следовательно, будет иметь эффект только внутри подоболочки. Однако мы можем использовать условное назначение параметра${name=word}
для установки mapping[$base]
, только если оно не установлено.
typeset -A mapping; mapping=()
zmv -w '*.foo.*' '${mapping[${1}]=$(openssl rand -hex 16)}.foo.$2'
Использование zmv с декомпозицией, которая не использует преимущества .foo
, как и в более сложном примере в (1. )выше, приводит к гораздо более сложному коду. Просто для примера вот вызов zmv для детерминированного случая, использующий base
в качестве временной переменной для хранения базового имени. Он использует ${name::=word}
для назначения переменной во время расширения параметра,и ${…}[0]
для подавления этой части расширения([0]
берет подстроку из 0-го символа, которого не существует, поскольку zsh начинает нумерацию элементов массива и строковых символов с 1; что-то вроде [2,1]
также будет работать ).
zmv '*.(<->|baz|bar<->.baz)' '${${base::=${f%%(.(<->|baz|bar<->(|-<->).baz))#}}[0]}${"$(openssl dgst -sha256 -hmac $secret <<<$base)"[-16,-1]}.${f#$base}'