Это должно делать то, что вы хотите. Я уверен, что кто-нибудь сможет это улучшить. В этих примерах я подразумеваю сжатый tar-архив с помощью gzip, поскольку он является наиболее распространенным.
Вам нужен архив, в котором нет одноуровневых узлов в дереве каталогов корневого уровня.
Каждая запись в списке содержимого tar должна начинаться с одного и того же шаблона. Этот шаблон является базовым путем к каталогу, который должен использоваться всеми записями в архиве. Если какие-либо две записи не начинаются с одного и того же образца, они являются братьями и сестрами.
Первая строка в списке содержимого tar даст вам минимальный шаблон, который вам нужно проверить. Это БАЗЕПАТ.
BASEPATH=$(tar ztf example.tar.gz | (read line; echo $line))
Затем, чтобы проверить на наличие взрывоопасных архивов tar, необходимо проверить, не начинается ли любая строка списка содержимого tar с BASEPATH.
tar ztf example.tar.gz | grep -qv "^${BASEPATH}"
Превратите это в функцию оболочки:
is_explosive() {
TARBALL_NAME=$1
tar ztf "${TARBALL_NAME}" | grep -qv "^$(tar ztf "${TARBALL_NAME}" | (read line; echo ${line}))"
return $?
}
Отсюда вы можете написать безопасную функцию извлечения tar-архива.
is_explosive() {
TARBALL_NAME=$1
tar ztf "${TARBALL_NAME}" | grep -qv "^$(tar ztf "${TARBALL_NAME}" | (read line; echo ${line}))"
return $?
}
safe_tar_x() {
TARBALL_NAME=$1
if is_explosive ${TARBALL_NAME}; then
SUBDIR=${TARBALL_NAME%.tar.gz}
SUBDIR=${SUBDIR##*/}
mkdir "${SUBDIR}"
echo "WARNING: This tarball is explosive. Opening in subdirectory, ${SUBDIR}, for safety." >&2
else
SUBDIR="."
fi
# Tar quirks: "--directory" must be last, and using more than
# one option group requires that all groups start with a dash.
tar -zxf "${TARBALL_NAME}" --directory "${SUBDIR}"
return $?
}
Le ha pedido explícitamente a find
que busque archivos(-type f
)y, cuando encuentre uno, le ha pedido que ejecute ls -lS
en él. Ni siquiera puede arreglar esto con la extensión de búsqueda de GNU de +
para pasar más de un archivo coincidente a la vez, ya que es probable que ()haya demasiados archivos para pasar a ls
a la vez.
En su lugar, usando GNU find, pídale que imprima el tamaño del archivo y el nombre del archivo, luego páselo a sort
, todo nulo -delimitado.
find /usr -type f -printf "%s %p\n\0"|sort -zn
Muestra de salida:
0 /usr/lib/python2.7/dist-packages/pkg_resources/_vendor/__init__.py
0 /usr/lib/python2.7/dist-packages/python_debian-0.1.30.egg-info/requires.txt
0 /usr/lib/python2.7/email/mime/__init__.py
... output omitted...
24013304 /usr/lib/gcc/i686-linux-gnu/6/cc1plus
25675008 /usr/lib/i386-linux-gnu/libicudata.so.57.1
49547156 /usr/lib/i386-linux-gnu/libLLVM-3.9.so.1
Si desea que la salida tenga el formato ls -l
, puede usar
find. -type f -exec ls -l {} \;|sort -n -k5
Muestra
$ find. -type f -exec ls -l {} \;|sort -n -k5
-rw-rw----+ 1 utsav utsav 0 Mar 6 02:23./file5.txt
-rw-rw----+ 1 utsav utsav 12 Mar 6 01:57./a.txt
-rw-rw----+ 1 utsav utsav 15 Mar 6 02:10./foo.txt
-rw-rw----+ 1 utsav utsav 15 Mar 6 02:11./c.txt
-rw-rw----+ 1 utsav utsav 27 Mar 6 01:57./b.txt