Способ CLI для сжатия отдельных файлов, находящихся в настоящее время в сжатой папке

У меня есть 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) и помещены в папку.

Edit2;

Я закончил 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
5
задан 24 November 2017 в 16:23

12 ответов

Вы можете использовать операцию «копирования» 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, потому что его выходной формат выглядит немного шелушащимся на разных и я хочу, по крайней мере, избегать языковых зависимостей.

5
ответ дан 22 May 2018 в 15:57

Вы можете использовать операцию «копирования» 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, потому что его выходной формат выглядит немного шелушащимся на разных и я хочу, по крайней мере, избегать языковых зависимостей.

6
ответ дан 18 July 2018 в 02:44

Вы можете использовать операцию «копирования» 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, потому что его выходной формат выглядит немного шелушащимся на разных и я хочу, по крайней мере, избегать языковых зависимостей.

6
ответ дан 24 July 2018 в 17:38

Это должно быть в состоянии сделать то, что вы хотите:

#!/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
...
3
ответ дан 22 May 2018 в 15:57
  • 1
    Хорошо, я думаю, что подстановочный знак * должен быть достаточным? – George Udosen 24 November 2017 в 03:18
  • 2
    Позвольте мне изменить его! – George Udosen 24 November 2017 в 03:23
  • 3
    Спасибо за обновление. Я думаю, что все еще есть проблема. Когда я делаю ./GU_unzip.sh Data.zip, я получаю zillions ошибок, подобных этому: caution: filename not matched: Data/Data/FMV0017!","O","47.450000","6","" zip warning: name not matched: ftmp/FMV0017!","O","47.450000","6","" .zip)rror: Nothing to do! (Data_zipped/FMV0017!","O","47.450000","6","" Archive: Data.zip [Я думаю, что строки FMV0017!... - это отдельные строки данных csv-файлов] – user2413 24 November 2017 в 12:56
  • 4
    Держись, я предоставил лучшую и обновленную версию благодаря @dessert – George Udosen 24 November 2017 в 13:39
  • 5
    Я в конечном итоге выбрал решение @David Foerster, потому что он избегает промежуточного сжатия / декомпрессии. Но я объединил его идею с интерфейсом, который вы написали, так как это было супер удобно использовать;) Спасибо! – user2413 24 November 2017 в 16:24

Рассматривали ли вы просмотр файловой системы с поддержкой zip?

Это в основном предоставляет zip-файл как обычный каталог, который любое приложение может открывать и читать файлы, тогда как библиотека плавких предохранителей обрабатывает грязные детали чтения и записи сжатого потока.

На Ubuntu вы можете установить его с помощью sudo apt install fuse-zip

. После установки плагина-плагина вы можете установить zip-файл с fuse-zip /path/to/some.zip mnt/ , где mnt - пустой каталог по вашему выбору.

После завершения размонтируйте его с помощью fusermount -u mnt/, где mnt - это каталог, в котором вы его установили.

fuse-zip будет даже создайте zip «на лету» для вас, если он не возбуждает.

2
ответ дан 22 May 2018 в 15:57

вы можете разархивировать файлы, содержащиеся в 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
1
ответ дан 22 May 2018 в 15:57
  • 1
    Это можно сделать с помощью «для всех файлов в Data.zip/Data/». На самом деле у меня нет простой повторяющейся структуры имен файлов внутри Data.zip/Data/. Я редактирую вопрос, чтобы лучше настроить задачу (извините за первую версию вопроса быть немного выключенным)? – user2413 23 November 2017 в 22:43
  • 2
    Вы можете получить список своих файлов с помощью unzip -l Data.zip > /tmp/files, а затем отредактировать полученный файл, чтобы он содержал только ваши имена файлов (например, с вырезанием). Затем вы можете использовать цикл: для i в `cat / tmp / files` делать ... BTW: Я забыл удалить несжатые файлы в моем выше скрипте (теперь отредактирован). – muclux 24 November 2017 в 02:12
  • 3
    `seq 1 100` можно заменить на {1..100} в bash, это Расширение брекета . – dessert 24 November 2017 в 03:23

вы можете разархивировать файлы, содержащиеся в 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
1
ответ дан 18 July 2018 в 02:44

Это должно быть в состоянии сделать то, что вы хотите:

#!/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 ...
3
ответ дан 18 July 2018 в 02:44

Рассматривали ли вы просмотр файловой системы с поддержкой zip?

Это в основном предоставляет zip-файл как обычный каталог, который любое приложение может открывать и читать файлы, а библиотека плавких предохранителей обрабатывает грязные детали чтения и записи сжатого потока.

На Ubuntu вы можете установить его с помощью sudo apt install fuse-zip

. После установки плагина-плагина вы можете установить zip-файл с fuse-zip /path/to/some.zip mnt/ , где mnt - пустой каталог по вашему выбору.

После завершения размонтируйте его с помощью fusermount -u mnt/, где mnt - это каталог, в который вы его установили.

fuse-zip будет даже создайте zip «на лету» для вас, если он не возбуждает.

2
ответ дан 18 July 2018 в 02:44

вы можете разархивировать файлы, содержащиеся в 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
1
ответ дан 24 July 2018 в 17:38
  • 1
    Это можно сделать с помощью «для всех файлов в Data.zip/Data/». На самом деле у меня нет простой повторяющейся структуры имен файлов внутри Data.zip/Data/. Я редактирую вопрос, чтобы лучше настроить задачу (извините за первую версию вопроса быть немного выключенным)? – user2413 23 November 2017 в 22:43
  • 2
    Вы можете получить список своих файлов с помощью unzip -l Data.zip > /tmp/files, а затем отредактировать полученный файл, чтобы он содержал только ваши имена файлов (например, с вырезанием). Затем вы можете использовать цикл: для i в `cat / tmp / files` делать ... BTW: Я забыл удалить несжатые файлы в моем выше скрипте (теперь отредактирован). – muclux 24 November 2017 в 02:12
  • 3
    `seq 1 100` можно заменить на {1..100} в bash, это Расширение брекета . – dessert 24 November 2017 в 03:23

Это должно быть в состоянии сделать то, что вы хотите:

#!/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 ...
3
ответ дан 24 July 2018 в 17:38
  • 1
    Хорошо, я думаю, что подстановочный знак * должен быть достаточным? – George Udosen 24 November 2017 в 03:18
  • 2
    Позвольте мне изменить его! – George Udosen 24 November 2017 в 03:23
  • 3
    Спасибо за обновление. Я думаю, что все еще есть проблема. Когда я делаю ./GU_unzip.sh Data.zip, я получаю zillions ошибок, подобных этому: caution: filename not matched: Data/Data/FMV0017!","O","47.450000","6","" zip warning: name not matched: ftmp/FMV0017!","O","47.450000","6","" .zip)rror: Nothing to do! (Data_zipped/FMV0017!","O","47.450000","6","" Archive: Data.zip [Я думаю, что строки FMV0017!... - это отдельные строки данных csv-файлов] – user2413 24 November 2017 в 12:56
  • 4
    Держись, я предоставил лучшую и обновленную версию благодаря @dessert – George Udosen 24 November 2017 в 13:39
  • 5
    Я в конечном итоге выбрал решение @David Foerster, потому что он избегает промежуточного сжатия / декомпрессии. Но я объединил его идею с интерфейсом, который вы написали, так как это было супер удобно использовать;) Спасибо! – user2413 24 November 2017 в 16:24

Рассматривали ли вы просмотр файловой системы с поддержкой zip?

Это в основном предоставляет zip-файл как обычный каталог, который любое приложение может открывать и читать файлы, а библиотека плавких предохранителей обрабатывает грязные детали чтения и записи сжатого потока.

На Ubuntu вы можете установить его с помощью sudo apt install fuse-zip

. После установки плагина-плагина вы можете установить zip-файл с fuse-zip /path/to/some.zip mnt/ , где mnt - пустой каталог по вашему выбору.

После завершения размонтируйте его с помощью fusermount -u mnt/, где mnt - это каталог, в который вы его установили.

fuse-zip будет даже создайте zip «на лету» для вас, если он не возбуждает.

2
ответ дан 24 July 2018 в 17:38

Другие вопросы по тегам:

Похожие вопросы: