2022年12月31日 星期六

LINUX 壓縮指令整理,如何在 Linux 上壓縮文件

LINUX 壓縮指令整理,如何在 Linux 上壓縮文件

有許多工具可用於在 Linux 系統上壓縮文件,但它們的行為方式或產生的壓縮級別各不相同。在這篇文章中,我們比較了其中的五個。

5種壓縮方法與教學

Linux 上有很多用於壓縮文件的命令。最新和最有效的方法之一是xz,但它們都具有節省磁盤空間和保留文件供以後使用的優點。在這篇文章中,我們比較了壓縮命令並指出了顯著差異。

tar

tar 命令不是專門的壓縮命令。它通常用於將多個文件合併為一個文件,以便於傳輸到另一個系統或將文件作為相關組進行備份。它還提供壓縮作為一項功能,這很有意義,並且可以添加z壓縮選項來實現這一點。 當使用z選項將壓縮添加到tar命令時,tar 使用gzip進行壓縮。 您可以使用tar像壓縮一個文件一樣輕鬆地壓縮單個文件,儘管這與直接使用gzip相比沒有什麼特別的優勢。要為此使用tar,只需像使用“tar cfz newtarfile 文件名”命令識別一組文件一樣識別文件,如下所示:
$ tar cfz bigfile.tgz bigfile
            ^            ^
            |            |
            +- 新文件 +- 要壓縮的文件
$ ls -l bigfile*
-rw-rw-r-- 1 shs shs 103270400 4 月 16 日 16:09 大文件
-rw-rw-r-- 1 shs shs 21608325 Apr 16 16:08 bigfile.tgz
請注意文件大小的顯著減少。 如果您願意,可以使用tar.gz擴展名,這可能會使文件的特徵更加明顯,但大多數 Linux 用戶可能會認為tgz的含義相同 – tar和gz的組合表示該文件是一個壓縮的 tar 文件。壓縮完成後,您將同時獲得原始文件和壓縮文件。 要將多個文件收集在一起並在一個命令中壓縮生成的“tar ball”,請使用相同的基本語法,但將文件指定為一組而不是單個文件。這是一個例子:
$ tar cfz bin.tgz bin/* 
          ^        ^ 
          |        |-- 要包含的文件
          新文件

zip

zip命令創建一個壓縮文件,同時保持原始文件不變。語法很簡單,除了與tar一樣,您必須記住原始文件應該是命令行的最後一個參數。
$ zip ./bigfile.zip bigfile
更新:bigfile(縮小 79%)
$ ls -l bigfile bigfile.zip
-rw-rw-r-- 1 shs shs 103270400 4 月 16 日 11:18 bigfile
-rw-rw-r-- 1 shs shs 21606889 Apr 16 11:19 bigfile.zip

gzip

gzip命令使用起來非常簡單。您只需鍵入“gzip”,然後鍵入要壓縮的文件的名稱。與上述命令不同,gzip將“就地”加密文件。換句話說,原始文件將被加密文件替換。
$ gzip bigfile
$ ls -l bigfile*
-rw-rw-r-- 1 shs shs 21606751 Apr 15 17:57 bigfile.gz

bzip2 

與gzip命令一樣,bzip2將“就地”壓縮您選擇的文件,只留下原始文件。
$ bzip bigfile
$ ls -l bigfile*
-rw-rw-r-- 1 shs shs 18115234 4 月 15 日 17:57 bigfile.bz2

xz 

作為壓縮命令團隊的新成員,xz在壓縮文件方面處於領先地位。與前兩個命令一樣,您只需向命令提供文件名。同樣,原始文件被壓縮到位。
$ xz bigfile
$ ls -l bigfile*
-rw-rw-r-- 1 shs shs 13427236 4 月 15 日 17:30 bigfile.xz

對於大文件,您可能會注意到xz比其他壓縮命令運行時間更長,但壓縮結果非常可觀。

比較

雖然大家都愛比大小 OwO,但是“大小不是一切”。因此,讓我們比較文件大小以及在製定壓縮文件計劃時要考慮的其他一些問題。 下面顯示的統計數據都與壓縮單個文件有關——bigfile——在上面顯示的示例命令中使用。該文件是一個很大且相當隨機的文本文件。壓縮率在某種程度上取決於文件​​的內容。


各種壓縮方式大小比較

比較時,上面顯示的各種壓縮命令產生了以下結果。百分比表示壓縮文件與原始文件的比較情況。
-rw-rw-r-- 1 shs shs 103270400 4 月 16 日 14:01 大文件
---------------------------------------------- ----
-rw-rw-r-- 1 shs shs 18115234 4 月 16 日 13:59 bigfile.bz2 ~17%
-rw-rw-r-- 1 shs shs 21606751 Apr 16 14:00 bigfile.gz ~21%
-rw-rw-r-- 1 shs shs 21608322 4 月 16 日 13:59 bigfile.tgz ~21%
-rw-rw-r-- 1 shs shs 13427236 4 月 16 日 14:00 bigfile.xz ~13%
-rw-rw-r-- 1 shs shs 21606889 Apr 16 13:59 bigfile.zip ~21%
xz命令獲勝,最終只有原始文件大小的 13%,但所有這些壓縮命令都顯著減小了原始文件的大小。


是否替換原文件

bzip2、gzip和xz命令都用壓縮版本替換原始文件。tar和zip命令不行。


壓縮時間

大小以外,時間也是問題OuO,不過我們喜歡快一點的,xz命令似乎比其他命令花費更多時間來加密文件。對於大文件,大概時間是: 命令運行時
tar 4.9 秒
zip 5.2 秒
bzip2 22.8 秒
gzip 4.8 秒
xz 50.4 秒
減壓時間可能比壓縮時間小得多。


文件權限

無論您在原始文件上設置了什麼權限,壓縮文件的權限都將基於您的umask設置,但保留原始文件權限的bzip2除外。


與 Windows 的兼容性

zip命令創建一個可以在 Windows 系統以及 Linux 和其他 Unix 系統上使用(即解壓縮)的文件,而無需安裝其他可能可用或可能不可用的工具。


解壓縮教學

解壓縮文件的命令與壓縮文件的命令類似。在運行上面顯示的壓縮命令後,這些命令將用於解壓縮大文件。
tar: tar xf bigfile.tgz
zip: unzip bigfile.zip
gzip: gunzip bigfile.gz
bzip2: bunzip2 bigfile.gz2
xz: xz -d bigfile.xz or unxz bigfile.xz


運行您自己的壓縮比較

如果您想自己運行一些測試,請獲取一個大但可替換的文件並使用上面顯示的每個命令壓縮它——最好使用一個新的子目錄。如果您想將xz包含在測試中,您可能必須先安裝它。此腳本可以使比較更容易,但可能需要幾分鐘才能完成。
#!/bin/bash

# ask user for filename
echo -n "filename> "
read filename

# you need this because some commands will replace the original file
cp $filename $filename-2

# clean up first (in case previous results are still available)
rm $filename.*

tar cvfz ./$filename.tgz $filename > /dev/null
zip $filename.zip $filename > /dev/null
bzip2 $filename
# recover original file
cp $filename-2 $filename
gzip $filename
# recover original file
cp $filename-2 $filename
xz $filename

# show results
ls -l $filename.*

# replace the original file
mv $filename-2 $filename

2017年10月30日 星期一

Arduino GPS ublox NEO 6M 相關教學

之前玩Arduino用到了UART的GPS模塊,芯片是uBLOX的NEO-6M GPS模組,用這款GPS的人其實不少,寫個筆記。



[模塊介紹如下]
1, 模塊采用U-BLOX NEO-6M模組,體積小巧,性能優異。
2, 有放大電路,有利於無源陶瓷天線快速搜星。
3, 模塊可通過UART進行各種參數設置,並可保存在EEPROM,使用方便。
4, 模塊自帶SMA接口,可以連接各種有源天線,適應能力強。
5, 模塊兼容3.3V/5V電壓,方便連接各種單晶片。
6, 模塊自帶可充電後備電池,可以掉電保存數據。

[通信協議]

GPS模塊采用NMEA 0183協議,NMEA 0183是美國國家海洋電子協會(National Marine Electronics Association)為海用電子設備制定的標準格式。目前業已成了GPS導航設備統一的RTCM(Radio Technical Commission for Maritime services)標準協議。
NMEA-0183協議采用ASCII碼來傳遞GPS定位信息,我們稱之為幀(frame)。

幀格式形如:$aaccc,ddd,ddd,„,ddd*hh(換行符CR+LF)

1、“$”:幀命令起始位
2、aaccc:地址域,前兩位為識別符(aa),後三位為語句名(ccc)
3、ddd,.....,ddd:數據
4、"*":校驗和前綴(也可以作為語句數據結束的標志)
5、hh:校驗和,$與*之間所有字符ASCII碼的校驗和(各字節做XOR運算,得到校驗和後,再轉換HEX)
6、(CR+LF):幀結束,ENTER和換行符



最常用的Data是第4個,即GPRMC,推薦定位信息(Recommended Minimum Specific GPS/Transit Data),長度70字節。

$GPRMC,(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)*hh(CR+LF)

(1)  UTC時間,hhmmss(時分秒)
(2)  定位狀態,A=有效定位,V=無效定位
(3)  緯度ddmm.mmmmm(度分)
(4)  緯度半球N(北半球)或S(南半球)
(5)  經度dddmm.mmmmm(度分)
(6)  經度半球E(東經)或W(西經)
(7)  地面速率(000.0~999.9節)
(8)  地面航向(000.0~359.9度,以真北方為參考基準)
(9)  UTC日期,ddmmyy(日月年)
(10) 磁偏角(000.0~180.0度,前導位數不足則補0)
(11) 磁偏角方向,E(東)或W(西)
(12) 模式指示(A=自主定位,D=差分,E=估算,N=數據無效)

舉例如下:

$GPRMC,023543.00,A,2308.28715,N,11322.09875,E,0.195,,240213,,,A*78

[PC端顯示數據]

GPS模塊有一個電腦版軟體叫u-Center,可以對模塊進行參數設置保存到EEPROM,其實也可以通過單晶片UART通信進行設置,但是PC端設置更加人性化,可以立刻看到結果。
打開GPS模塊之後,接上u-Center軟件,可以看到如下數據。
$GPVTG,,,,,,,,,N*30
$GPGGA,160444.00,,,,,0,00,99.99,,,,,,*65
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,3,1,10,03,09,252,24,08,27,206,18,09,08,321,,14,25,160,*77
$GPGSV,3,2,10,16,56,322,,22,08,231,,26,50,016,,27,62,189,*71
$GPGSV,3,3,10,31,45,084,,32,08,156,*7C
$GPGLL,,,,,160444.00,V,N*49
$GPRMC,160445.00,V,,,,,,,291017,,,N*73
$GPVTG,,,,,,,,,N*30
$GPGGA,160445.00,,,,,0,00,99.99,,,,,,*64
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,3,1,10,03,09,252,24,08,27,206,18,09,08,321,,14,25,160,*77
$GPGSV,3,2,10,16,56,322,,22,08,231,,26,50,016,,27,62,189,*71
$GPGSV,3,3,10,31,45,084,,32,08,156,*7C
$GPGLL,,,,,160445.00,V,N*48
$GPRMC,160446.00,V,,,,,,,291017,,,N*70
...
...
***可以去u-center 的 Config → Configuration把大量訊息關閉,留下GPRMC就好,提升MCU效率

以上GPS還沒定到位,若有定到位,$GRPMC會如下:
...
$GPRMC,133306.00,A,3949.63075,N,11616.48616,E,0.513,,120116,,,A*7A
$GPRMC,133307.00,A,3949.63025,N,11616.48614,E,1.053,,120116,,,A*7C
$GPRMC,133308.00,A,3949.63002,N,11616.48641,E,1.101,,120116,,,A*70
...

2017年10月22日 星期日

[Contiki] CC1310 SimpleLink / CC2650 UART、LED 使用範例

最近在玩Contiki OS,用的是CC1350的板子,每次有問題都是靠一位很強大的大大協助指點,或是爬爬大部分都是英文的資料,想說乾脆之後做過的東西都打起來,當個備忘,也給想看的人。

CC13xx/CC26xx 的Sample code 基本上都通用,編譯的時候用 make TARGET=srf06-cc26xx BOARD=launchpad/cc1350 [app-name] 就OK了,1350那邊改成你自己的板子

先從UART 跟 LED開始講起吧,雖然很基本,但是我很蠢的搞了很久XD。

[是從官方的examples改出來的]
#include "contiki.h"
#include "dev/cc26xx-uart.h"
#include "dev/serial-line.h"
#include "dev/leds.h"
#include <stdio.h>
#include <string.h>

PROCESS(test_serial_led, "Serial line and led test process");
AUTOSTART_PROCESSES(&test_serial_led);

PROCESS_THREAD(test_serial_led, ev, data) 
{
    PROCESS_BEGIN();
    cc26xx_uart_set_input(serial_line_input_byte); //反正要偵聽terminal輸入就是用他就對了,管他26xx還是13xx,都通用的
    printf("Hello, world.\n");

    while(1) 
    {
        PROCESS_YIELD();
        if (ev == serial_line_event_message) //監聽到的事件等於serial line輸入( terminal打字 + [Alt-Enter] )
        {
            printf("Received String = %s\n", (char * ) data);
            if (strcmp(data, "ON") == 0) leds_on(LEDS_GREEN); //如果收到字串是"ON"就開綠燈
            else if (strcmp(data, "OFF") == 0) leds_off(LEDS_GREEN); //如果收到字串是"OFF"就關燈
        }
    }
    PROCESS_END();
}

2017年10月19日 星期四

Open Street Map (OSM) 圖磚(tile map)簡介、經緯度座標互換方式

osm 圖磚(tile)簡介 與 經緯度座標 互換方式

openstreemap tile conversion
開放街圖 圖磚 換算方法

這邊講的Tile是指osm儲存圖資的方式之一,簡單來說,你在www.openstreetmap.org的地圖縮放時,可以看到慢慢讀取出來一塊塊方塊的圖片,湊成大地圖,一塊塊的東西就是tile,這些tile就是把圓的地球表面,投影到平面上所做出來的資料。

為了方便分別不同資料密度,tile有一個「zoom level」也就是縮放等級,從0~19,[Level 0]代表把地球投影成一張正方形圖片,[Level 1]就是把[Level 0]切成四個正方形,依此往下,呈現的資料越來越精細,下圖簡略表示之。


而由於球體有弧度,所以經緯度對應到平面上時,也有相應的計算方式。

###long/lat to tile num 經緯度換算圖磚ID###
###2017/10/19###

#coding: utf8

import math

lat_degree = 23.543210 #緯度
lon_degree = 121.012345 #經度
zoom_level = 15 #縮放倍率

lat_radian = math.radians(lat_degree) #角度轉弧度
n = 2.0 ** zoom_level #tile數的單邊格子數
x_tile = int((lon_degree + 180.0) / 360.0 * n)
y_tile = int((1.0 - math.log(math.tan(lat_radian) + (1 / math.cos(lat_radian))) / math.pi) / 2.0 * n)
print(x_tile, y_tile) #圖磚x 圖磚y


所以說,以 [東經121.012345, 北緯23.543210, 縮放倍率15] 算出來的圖磚ID是 (15,27398,14178) 可以用網址 a.tile.openstreetmap.org/15/27398/14178.png 看到這塊圖磚 (僅供參考,這樣的圖磚讀取方法違反OSM使用規範) 反之,我現在知道了圖磚的ID,我想知道該圖磚的經緯度就要反算

###Tile to long/lat 圖磚轉經緯度###
###2017/10/19###

#coding: utf8

import math

x_tile = 27398
y_tile = 14178
zoom_level = 15
n = 2.0 ** zoom_level
lon_degree = x_tile / n * 360.0 - 180.0
lat_radian= math.atan(math.sinh(math.pi * (1 - 2 * y_tile / n)))
lat_degree = math.degrees(lat_radian)
print(lat_degree, lon_degree)

算出來的經緯度是23.543845136505837, 121.00341796875,為毛呢QAQ,因為這是計算「該圖磚最左上角(North-West)的經緯度」,所以如果你要算圖磚中心的經緯度,就要把x_tile跟y_tile加0.5就可以了,同理可知,要計算圖磚上任意點的經緯度,就是用比例去算一下,再往回推囉。

2016年10月24日 星期一

Python Reportlib 生產各式<檔案><報表><發票>,背景列印PDF,Pywin32,Acrobat 系列 ...


以下是用Python裡面的Reportlib模組產生自己喜歡的PDF,
可以依照你要的頁面、紙張或印表機自訂大小,
例如名片、發票、收據、感熱列印機等等。 非常之好用。


###code by shadowwolf###
###2016/10/24###

#coding: utf8

import reportlab
from reportlab.pdfgen import canvas
from reportlab.lib.units import mm

pdf_file_name="D:/name_you_want.pdf"
c = reportlab.pdfgen.canvas.Canvas(pdf_file_name)
c.setPageSize((82.5*mm, 50*mm)) #自訂義頁面寬度、高度
#以下就是在canvas上加東加西,詳情請上官網查詢Documentation
c.drawString(10,10,"Hello World")
c.drawString(50,50,"Hello World2")
c.drawString(100,100,"Hello World3")
c.showPage() #產生頁面
c.save() #存檔

產生PDF之後,再用Acrobat的SDK(用Pywin32呼叫)。
記得要裝Acrobat的standard或是pro版,
我有用Acrobat 7, Acrobat XI試過都可以。
以下會以靜默模式把PDF文件丟入列印佇列,
並且用預設印表機 印出來

from win32com.client import Dispatch
avdoc = Dispatch('AcroExch.AVDoc')
avdoc.Open(pdf_file_name, 'name')
pages = avdoc.GetPDDoc().GetNumPages()
avdoc.PrintPagesSilent(0, pages-1, 3, 1, 0) ### 開始頁(0開始), 結束頁, PS, 二維碼, 是否縮放

2016年7月8日 星期五

Django + apache2 (wsgi) 部署 deploy 粗略筆記

裝Apache
sudo apt-get install apache2
裝WSGI
#Python 2
sudo apt-get install libapache2-mod-wsgi
#Python 3
sudo apt-get install libapache2-mod-wsgi-py3
新增apache2 sites-available (/etc/apache2/ 底下找)
<VirtualHost *:80>
ErrorLog /etc/apache2/error.log
ServerName www.yourdomain.com
ServerAlias otherdomain.com
ServerAdmin youmail@gmail.com 
Alias /media/ /var/www/site/PROJECT/media/
Alias /static/ /var/www/site/PROJECT/static/ 
<Directory /var/www/site/PROJECT/media>
Require all granted
</Directory> 
<Directory /var/www/site/PROJECT/static>
Require all granted
</Directory> 
WSGIScriptAlias / /var/www/site/PROJECT/PROJECT/wsgi.py

<Directory /var/www/site/PROJECT/PROJECT>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
</VirtualHost>
wsgi.py設定
import os, sys
from os.path import join,dirname,abspath
PROJECT_DIR = dirname(dirname(abspath(__file__)))
sys.path.append('/var/www/site/PROJECT')
#看python版本!!
sys.path.append('/var/www/venv/PROJECT/lib/python2.7/site-packages') 
os.environ["DJANGO_SETTINGS_MODULE"] = 'PROJECT.settings'
from django.core.wsgi import get_wsgi_application 
application = get_wsgi_application()
改dir權限 /etc/apache2/envvars 可改使用apache2之用戶,預設www-data
sudo chmod -R 644 PROJECT
sudo find PROJECT -type d -exec chmod 755 \{\} \;
>>改static權限 [settings.py]
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR,'static')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
改用戶權限 (有用到upload或db才需要)
sudo chgrp -R www-data uploads
sudo chmod -R g+w uploads

sudo chgrp www-data PROJECT
sudo chmod g+w PROJECT
sudo chgrp www-data PROJECT/db/db.sqlite3
sudo chmod g+w PROJECT/db/db.sqlite3
啟動
sudo a2ensite PROJECT
sudo service apache2 reload

2013年5月3日 星期五

WinSocket POST (x64 Win7 DevCpp) 備忘

加入的Linker 
-static-libstdc++ -static-libgcc -lwsock32 -lws2_32

Code



#define _WIN32_WINNT 0x501
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

// 連結 Ws2_32.lib, Mswsock.lib, Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define default_BUFLEN 2147489
#define default_PORT "80"

char recvbuf[default_BUFLEN];
int count=0;

int __cdecl main(int argc, char **argv)
{
 WSADATA wsaData;
 SOCKET ConnectSocket = INVALID_SOCKET;
 addrinfo *result=NULL,*ptr = NULL,hints;
 char *ID = ##此處為封包內容##;



 while(1)
 { 
  Sleep(500);
  int iResult;
  int recvbuflen=default_BUFLEN;

  // Initialize Winsock
  iResult = WSAStartup(MAKEWORD(2,2), &wsaData);

  if (iResult != 0) 
  {
   printf("WSAStartup failed with error: %d\n", iResult);
   return 1;
  }

  ZeroMemory(&hints, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;
  // 解析PORT跟IP
  char *a= ##目標IP##;
  iResult = getaddrinfo(a, default_PORT, &hints, &result);
  if ( iResult != 0 ) 
  {
   printf("getaddrinfo failed with error: %d\n", iResult);
   WSACleanup();
   return 1;
  }
  // 連
  for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) 
  {
   // 建立SOCKET連接
   ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
   if (ConnectSocket == INVALID_SOCKET) 
   {
    printf("socket failed with error: %ld\n", WSAGetLastError());
    WSACleanup();
    return 1;
   }
   // Connect to server.
   iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
   if (iResult == SOCKET_ERROR) 
   {
    closesocket(ConnectSocket);
    ConnectSocket = INVALID_SOCKET;
    continue;
   }
   break;
  }

  freeaddrinfo(result);
  if (ConnectSocket == INVALID_SOCKET) 
  {
   printf("Unable to connect to server!\n");
   WSACleanup();
   return 1;
  }
  
  // 發送初始包
  iResult = send( ConnectSocket, ID, (int)strlen(ID), 0 );
  if (iResult == SOCKET_ERROR) 
  {
   printf("send failed with error: %d\n", WSAGetLastError());
   closesocket(ConnectSocket);
   WSACleanup();
   return 1;
  }
  printf("Bytes Sent: %ld\n", iResult);

  // 斷開
  Sleep(10);
  iResult = shutdown(ConnectSocket, SD_SEND);
  if (iResult == SOCKET_ERROR) 
  {
   printf("shutdown failed with error: %d\n", WSAGetLastError());
   closesocket(ConnectSocket);
   WSACleanup();
   return 1;
  }

  // 在對方斷開前持續接收
  do 
  {
   iResult = recv(ConnectSocket, recvbuf, 214748, 0);
   if ( iResult > 0 ) printf("Bytes received: %d\n", iResult);
   else if ( iResult == 0 ) printf("Connection closed\n");
   else printf("recv failed with error: %d\n", WSAGetLastError());
  } 
  while( iResult > 0 );

  for(int tt = 0;tt < strlen(recvbuf);tt++) printf("%c",recvbuf[tt]);
  printf("==========================================\n");

  // cleanup
  closesocket(ConnectSocket);
  WSACleanup();
 }
 return 0;
}