У меня есть zipped-файл Data.zip, который (если несжатый) содержит много файлов:
file_1.txt
file_2.txt
...
...
Я хочу, чтобы команда CLI превратила это в новую папку Data_zipped, которая содержит отдельные файлы в Data.zip несжатые:
Data_zipped/file_1.zip
Data_zipped/file_2.zip
...
...
Но фокус в том, что Data.zip содержит так много файлов (и они все такие большие), что я не могу сначала распаковать Data.zip, а затем сжать отдельные файлы внутри него одним махом: все это должно произойти «на лету»:
Для всех файлов в Data.zip/
получить i-й файл, сжать его в name_of_that_file.zip сохранить сжатый файл в новой папке Data_zippedКак это сделать с помощью CLI?
Я модифицировал супер прозрачный скрипт Джорджа, чтобы лучше объяснить структуру папок:
#!/bin/bash
#Name of zip file
filename=$1
# Check if valid zip file is passed
if [[ $(file "$filename" | grep -o "Zip archive data") =~ "Zip archive data" ]]
then
# List the contents of the zip file
unzip -l "$filename"
# Get the number of files in zip file
count=$(unzip -l "$filename" | awk '{count = $2 - 2} END {print count}')
echo "$count"
fi
exit 0
Когда я запускаю его, я получаю (я использую токен Data.zip с несколькими файлами в нем, но вы получаете идею):
./GU_script.sh Data.zip
Archive: Data.zip
Length Date Time Name
--------- ---------- ----- ----
0 2017-11-21 22:58 Data/
120166309 2017-11-21 14:58 Data/Level1_file.csv
120887829 2017-11-21 14:58 Data/Level1_other_file.csv
163772796 2017-11-21 14:59 Data/Level1_yet_other_file.csv
193519556 2017-11-21 14:59 Data/Level1_here_is_another_file.csv
153798779 2017-11-21 14:59 Data/Level1_so_many_files.csv
131918225 2017-11-21 14:59 Data/Level1_many_more_to_go.csv
--------- -------
884063494 7 files
5
So в основном, я хотел бы, чтобы Level1_file.csv и другие файлы были заархивированы индивидуально (-> Level1_file.zip) и помещены в папку.
Я закончил u p, сочетая ответы @ George и @David Foerster:
#!/bin/bash
#Name of zip file
filename="$1"
# Check if valid zip file is passed
if file "$filename" | grep -wq "Zip archive data";
then
#!/bin/bash
src="$filename"
dst=.
LC_ALL=C unzip -l "$src" |
sed -re '1,/^-{6}/d; /^-{6}/,$d; /\/$/d; s/^\s*(\S+\s+){3}//' |
while IFS= read -r f; do
out="${f##*/}"; out="$dst/${f%%/*}_zipped/${out%.*}.zip"
if [ ! -d "${out%/*}" ]; then
mkdir -p "${out%/*}" || break
fi
zip --copy "$src" --out "$out" "$f" || break
done
else
echo "Invalid file type: \"zip\" file required"
exit 1
fi
Вы можете использовать операцию «копирования» zip(1) и некоторого изменения пути к файлу. Он имеет преимущество для копирования сжатых потоков данных непосредственно в целевой архив без прерывистой декомпрессии.
#!/bin/bash
src=Data.zip
dst=.
LC_ALL=C unzip -l "$src" |
sed -re '1,/^-{6}/d; /^-{6}/,$d; /\/$/d; s/^\s*(\S+\s+){3}//' |
while read -r f; do
out="${f##*/}"; out="$dst/${f%%/*}_zipped/${out%.*}.zip"
if [ ! -d "${out%/*}" ]; then
mkdir -p "${out%/*}" || break
fi
zip --copy "$src" --out "$out" "$f" || break
done
Я добавил LC_ALL=C к вызову unzip, потому что его выходной формат выглядит немного шелушащимся на разных и я хочу, по крайней мере, избегать языковых зависимостей.
Вы можете использовать операцию «копирования» zip(1) и некоторого изменения пути к файлу. Он имеет преимущество для копирования сжатых потоков данных непосредственно в целевой архив без прерывистой декомпрессии.
#!/bin/bash
src=Data.zip
dst=.
LC_ALL=C unzip -l "$src" |
sed -re '1,/^-{6}/d; /^-{6}/,$d; /\/$/d; s/^\s*(\S+\s+){3}//' |
while read -r f; do
out="${f##*/}"; out="$dst/${f%%/*}_zipped/${out%.*}.zip"
if [ ! -d "${out%/*}" ]; then
mkdir -p "${out%/*}" || return
fi
zip --copy "$src" --out "$out" "$f" <&- || return
done
Я добавил LC_ALL=C к вызову unzip, потому что его выходной формат выглядит немного шелушащимся на разных и я хочу, по крайней мере, избегать языковых зависимостей.
Вы можете использовать операцию «копирования» zip(1) и некоторого изменения пути к файлу. Он имеет преимущество для копирования сжатых потоков данных непосредственно в целевой архив без прерывистой декомпрессии.
#!/bin/bash
src=Data.zip
dst=.
LC_ALL=C unzip -l "$src" |
sed -re '1,/^-{6}/d; /^-{6}/,$d; /\/$/d; s/^\s*(\S+\s+){3}//' |
while read -r f; do
out="${f##*/}"; out="$dst/${f%%/*}_zipped/${out%.*}.zip"
if [ ! -d "${out%/*}" ]; then
mkdir -p "${out%/*}" || return
fi
zip --copy "$src" --out "$out" "$f" <&- || return
done
Я добавил LC_ALL=C к вызову unzip, потому что его выходной формат выглядит немного шелушащимся на разных и я хочу, по крайней мере, избегать языковых зависимостей.
Это должно быть в состоянии сделать то, что вы хотите:
#!/bin/bash
#Name of zip file
filename="$1"
# Check if valid zip file is passed
if file "$filename" | grep -wq "Zip archive data";
then
# List the contents of the zip file
unzip -l "$filename"
# Make the destination folder
# after checking they don't exist
if [ ! -d Data_zipped ];
then
mkdir Data_zipped
fi
#make temporary folder
#for extracted files
tempdir=$(mktemp -d)
# Make temporary file to hold the filenames
mysrc=$(mktemp)
# Get the filesnames from the zip folder
unzip -c Data.zip | cut -d" " -f3- | grep -E -o "[^Data/].*" | grep -Ev \(.zip\) | sed '/^\s*$/d' > "$mysrc"
while read -r var;
do
unzip -j "$filename" "Data/$var" -d "$tempdir/"
# Get name of file from each read line
zip Data_zipped/"$var".zip "$tempdir/$var"
# remove the original file
rm -rf "$tempdir/${var:?}"
done < "$mysrc"
else
echo "Invalid file type: \"zip\" file required"
exit 1
fi
Примечание:
Используемая структура дерева:
Data
├── file_10.txt
├── file_1.txt
...
Рассматривали ли вы просмотр файловой системы с поддержкой zip?
Это в основном предоставляет zip-файл как обычный каталог, который любое приложение может открывать и читать файлы, тогда как библиотека плавких предохранителей обрабатывает грязные детали чтения и записи сжатого потока.
На Ubuntu вы можете установить его с помощью sudo apt install fuse-zip
. После установки плагина-плагина вы можете установить zip-файл с fuse-zip /path/to/some.zip mnt/ , где mnt - пустой каталог по вашему выбору.
После завершения размонтируйте его с помощью fusermount -u mnt/, где mnt - это каталог, в котором вы его установили.
fuse-zip будет даже создайте zip «на лету» для вас, если он не возбуждает.
вы можете разархивировать файлы, содержащиеся в Data.zip, один за другим: unzip Data.zip file1.txt и сжать их.
mkdir Data_unzipped
for i in `seq 1 100` # or whatever the number of your files is
do
unzip Data.zip file_${i}.txt
zip Data_unzipped/file_${i}.zip file_${i}.txt
rm file_${i}.txt
done
вы можете разархивировать файлы, содержащиеся в Data.zip, один за другим: unzip Data.zip file1.txt и сжать их.
mkdir Data_unzipped
for i in `seq 1 100` # or whatever the number of your files is
do
unzip Data.zip file_${i}.txt
zip Data_unzipped/file_${i}.zip file_${i}.txt
rm file_${i}.txt
done
Это должно быть в состоянии сделать то, что вы хотите:
#!/bin/bash
#Name of zip file
filename="$1"
# Check if valid zip file is passed
if file "$filename" | grep -wq "Zip archive data";
then
# List the contents of the zip file
unzip -l "$filename"
# Make the destination folder
# after checking they don't exist
if [ ! -d Data_zipped ];
then
mkdir Data_zipped
fi
#make temporary folder
#for extracted files
tempdir=$(mktemp -d)
# Make temporary file to hold the filenames
mysrc=$(mktemp)
# Get the filesnames from the zip folder
unzip -c Data.zip | cut -d" " -f3- | grep -E -o "[^Data/].*" | grep -Ev \(.zip\) | sed '/^\s*$/d' > "$mysrc"
while read -r var;
do
unzip -j "$filename" "Data/$var" -d "$tempdir/"
# Get name of file from each read line
zip Data_zipped/"$var".zip "$tempdir/$var"
# remove the original file
rm -rf "$tempdir/${var:?}"
done < "$mysrc"
else
echo "Invalid file type: \"zip\" file required"
exit 1
fi
Примечание:
Используемая структура дерева:
Data
├── file_10.txt
├── file_1.txt
...
Рассматривали ли вы просмотр файловой системы с поддержкой zip?
Это в основном предоставляет zip-файл как обычный каталог, который любое приложение может открывать и читать файлы, а библиотека плавких предохранителей обрабатывает грязные детали чтения и записи сжатого потока.
На Ubuntu вы можете установить его с помощью sudo apt install fuse-zip
. После установки плагина-плагина вы можете установить zip-файл с fuse-zip /path/to/some.zip mnt/ , где mnt - пустой каталог по вашему выбору.
После завершения размонтируйте его с помощью fusermount -u mnt/, где mnt - это каталог, в который вы его установили.
fuse-zip будет даже создайте zip «на лету» для вас, если он не возбуждает.
вы можете разархивировать файлы, содержащиеся в Data.zip, один за другим: unzip Data.zip file1.txt и сжать их.
mkdir Data_unzipped
for i in `seq 1 100` # or whatever the number of your files is
do
unzip Data.zip file_${i}.txt
zip Data_unzipped/file_${i}.zip file_${i}.txt
rm file_${i}.txt
done
Это должно быть в состоянии сделать то, что вы хотите:
#!/bin/bash
#Name of zip file
filename="$1"
# Check if valid zip file is passed
if file "$filename" | grep -wq "Zip archive data";
then
# List the contents of the zip file
unzip -l "$filename"
# Make the destination folder
# after checking they don't exist
if [ ! -d Data_zipped ];
then
mkdir Data_zipped
fi
#make temporary folder
#for extracted files
tempdir=$(mktemp -d)
# Make temporary file to hold the filenames
mysrc=$(mktemp)
# Get the filesnames from the zip folder
unzip -c Data.zip | cut -d" " -f3- | grep -E -o "[^Data/].*" | grep -Ev \(.zip\) | sed '/^\s*$/d' > "$mysrc"
while read -r var;
do
unzip -j "$filename" "Data/$var" -d "$tempdir/"
# Get name of file from each read line
zip Data_zipped/"$var".zip "$tempdir/$var"
# remove the original file
rm -rf "$tempdir/${var:?}"
done < "$mysrc"
else
echo "Invalid file type: \"zip\" file required"
exit 1
fi
Примечание:
Используемая структура дерева:
Data
├── file_10.txt
├── file_1.txt
...
Рассматривали ли вы просмотр файловой системы с поддержкой zip?
Это в основном предоставляет zip-файл как обычный каталог, который любое приложение может открывать и читать файлы, а библиотека плавких предохранителей обрабатывает грязные детали чтения и записи сжатого потока.
На Ubuntu вы можете установить его с помощью sudo apt install fuse-zip
. После установки плагина-плагина вы можете установить zip-файл с fuse-zip /path/to/some.zip mnt/ , где mnt - пустой каталог по вашему выбору.
После завершения размонтируйте его с помощью fusermount -u mnt/, где mnt - это каталог, в который вы его установили.
fuse-zip будет даже создайте zip «на лету» для вас, если он не возбуждает.