-
-
-
-
-
- Tools
- Dev
- Bash
- Recherche web
-
Zim Desktop is a great software! It allows to create and manage one or more personnal wiki-like knowledge database, diligently and easily, on any desktop computer, without the use of any cloud service (preserving data privacy), and without the need of a webserver!
This web page is written to share my experience with persons who have minimal experience with both Zim Desktop and a debian based GNU/Linux operating system.
If you do not know the free software Zim Desktop yet, you can read this excellent presentation (PDF) from its creator Jaap Karssenberg and download the program from the official site (look at the bottom of zim page).
Working at my custommers'homes, I am often brought to fix computers whose are running under Microsoft Windows for the greater part. In addition to my differents tools such as Live Boot CDs/DVDs/USB sticks, portable programs and Windows batch programs, I have a huge polypropylene pockets display book filled by technical specifications and procedures of my own.
But the world of computers is like the medecine one: there is a continuous multiplication of IT sub-departments and IT specification references grow in the manner of an exponential curve. So like other perfectionist persons, I feed a personal IT notebook within Zim Desktop for years.
Synchronizing my IT Zim Desktop Linux notebook to my portableApps working USB stick before each intervention, I had to open it with the ultra-basic program notepad.exe for a long time, until I find the good way to make notebooks created within Zim Desktop Linux full compatibles both with Zim Dekstop Windows portable and Zim Dekstop Linux portable.
Below, I share my experience with other GNU/Linux users in order to port their own Zim notebooks to other PCs without the need to install Zim Desktop on them.
The following paragraph is about Zim Desktop Windows Portable (aka "Zim Desktop Wiki for Windows portable") with an example that locates it into the official PortableApps directory. But it can be located in any other place without the need of PortableApps plateform.
GNU/Linux users who are not familiar with rsync can look at the ubuntu related page.
Here is a file tree summary of Zim Windows Portable with two notebooks :
ZimDesktopWikiPortable/ ├── App/ ├── Data/ │ ├── Config/ │ │ └── zim/ │ │ ├── accelmap │ │ ├── notebooks.list │ │ ├── preferences.conf │ │ └── style.conf │ ├── Notebooks/ │ │ ├── my-first-notebook/ │ │ │ └── notebook.zim │ │ └── my-second-notebook/ │ │ └── notebook.zim │ └── settings/ ├── Other/ └── ZimDesktopWikiPortable.exe
The page "Config files" of the official manual introduces the default content of the environment path variables XDG_CONFIG_HOME and XDG_DATA_HOME used by Zim. At the time I wrote this lines (13 sep 2015) – not having inspected zim/config/basedirs.py of source project –, thoses informations for XDG_DATA_HOME seems to me a little confused or outdated1).
Regardless of the operating system Zim is running on, let's remember the invariant specification data and meta-data storage paths are:
$XDG_CONFIG_HOME/zim
: the directory the config files are stored into$XDG_DATA_HOME/Notebooks
: the default directory the notebooks files are stored intoZim Windows portable defaults this environment variables to the following values:
XDG_CONFIG_HOME = ZimDesktopWikiPortable/Data/Config
XDG_DATA_HOME = ZimDesktopWikiPortable/Data
Limitation for Zim Windows portable:
Even though Zim works perfectly with absolute path names, nobody can know in advance the absolute path name for a USB stick! For that reason, one can store a notebook into any other directory which it is a descendant of $XDG_DATA_HOME, but it is highly inadvisable to store a notebook outside of $XDG_DATA_HOME if one wants Zim Windows portable to access it.
Each notebook is made up of a standalone directory containing a single configuration file notebook.zim
wich specifies what End Of Line (EOL) type the notebook files are made of (unix, dos…). This is why all kinds of Zim versions running on all kinds of computers can access all kinds of notebooks regardless of the operation system they were created.
Also, there is nothing special to do with a rsync notebook target, except converting EOL of notebook.zim into the target operating system's one, so that it can be read.
Example of a file notebook.zim created by Zim Desktop Windows portable :
[Notebook] version=0.4 name=MyNewWiki interwiki= home=Home icon= document_root= shared=True endofline=dos disable_trash=False profile=
For data privacy, one must set the following options when working with Zim portable on a foreign computer:
shared=False
: make zim creates the buffer area on the USB stick rather than the hard diskdisable_trash=True
: make zim delete notebook pages and contents without moving to the hard disk trash can
Example of a file notebook.zim
that one must create if missing within a notebook directory called "MyNewWiki":
[Notebook] version=0.4 name=MyNewWiki interwiki= home=MyNewWiki icon= document_root= endofline=unix profile= shared=False disable_trash=True
The target file notebooks.list
must be created as follow :
$XDG_DATA_HOME
(ZimDesktopWikiPortable/Data), symbolised by tilde ~. For example, the path to MyNewNoteBook witch is located into ZimDesktopWikiPortable/Data/Notebooks/ will be: ~/Notebooks/MyNewNoteBook
[Notebook]
is written [Notebook N]
where N is an incremental number starting at 1, and in the [NotebookList]
section lines begining by path such as ~/Notebooks/a_name
are replaced with N=~/Notebooks/a_name
where N is an incremental number starting at 1)
Example of a file notebooks.list
created by Zim prior to version 0.61, and that we shall create for full compatibility:
[NotebookList] Default=~/Notebooks/MyNewWiki ~/Notebooks/MyNewWiki [Notebook] uri=~/Notebooks/MyNewWiki name=MyNewWiki interwiki=None icon=None
Example of a file notebooks.list
created by Zim as of version 0.61:
[NotebookList] Default=~/Notebooks/MyNewWiki 1=~/Notebooks/MyNewWiki [Notebook 1] uri=~/Notebooks/MyNewWiki name=MyNewWiki interwiki=None icon=None
Here is a BASH (fr) function I wrote to rsync one or more notebooks created under Zim Desktop Linux to a Zim Windows Portable base directory. Feel free to modify and bring it to your scripts. It works well under debian 7 and the following package depends are required: coreutils, bash, findutils, grep, sed, rsync.
Usage: rsync_zim_linux_to_zim_windows_portable [-v] source_dir dest_dir notebook1 [notebook2] [...] [notebookN] Options: -v : verbose mode to standard output
Example:
Assuming that:
All that I have to do within a BASH script is to call the function rsync_zim_to_zim_windows_portable() as following:
rsync_zim_to_zim_windows_portable -v $HOME/Documents/zim-database /media/usb_stick/PortableApps/ZimDesktopWikiPortable work personal
Here is the BASH function:
## Function to rsync one or more notebooks from linux zim to a windows ZimDesktopWikiPortable ## Note: Whatever OS is, each zim portable config file must contain UTF-8 CR/LF with UNIX slash ## Version: 1.0.1 ## Debian depends: coreutils, bash, findutils, grep, sed, rsync ## ## Usage: ## rsync_zim_linux_to_zim_windows_portable [-v] source_dir dest_dir notebook_name1 [notebook_name2] [...] [notebook_nameN] ## ## Options: ## -v : verbose mode to standard output ## ## ## Example with 2 notebooks: ## rsync_zim_linux_to_zim_windows_portable -v $HOME/Documents/zim-database /media/usb_stick/PortableApps/ZimDesktopWikiPortable work personal ## function rsync_zim_linux_to_zim_windows_portable() { local _VERBOSE="" local _OPTION unset OPTIND while getopts ":v" _OPTION; do case ${_OPTION} in v) _VERBOSE="-vvv";; esac done test $OPTIND -ne 1 && shift $(($OPTIND - 1)) local _ERROR=0 local _CONFIG_VER="0.4" local _NOTEBOOK_NR=1 local _SRC_DIR="$1" local _DST_DIR="$2" shift 2 test -d "${_SRC_DIR}" || return 1 test -d "${_DST_DIR}" || return 2 ## Init directories local _TEMP_DIR=`mktemp -d -p /tmp ${FUNCNAME}_XXXXXXXXXXXXXXXXXXXX` test -d "${_DST_DIR}/Data/Config/zim" || mkdir -p "${_DST_DIR}/Data/Config/zim" test -d "${_DST_DIR}/Data/Notebooks" || mkdir -p "${_DST_DIR}/Data/Notebooks" ## Prevent portable app warning by deleting last running path rm -f "${_DST_DIR}/Data/settings/ZimDesktopWikiPortableSettings.ini" ## 1/4 - General configuration files ## ${XDG_CONFIG_HOME:-$HOME/.config}/zim/preferences.conf -> "${_DST_DIR}/Data/Config/zim/preferences.conf" ## Copy the config file by converting LF to CR/LF test -f ${XDG_CONFIG_HOME:-$HOME/.config}/zim/preferences.conf && sed 's/$/\r/' ${XDG_CONFIG_HOME:-$HOME/.config}/zim/preferences.conf >"${_DST_DIR}/Data/Config/zim/preferences.conf" ## ${XDG_CONFIG_HOME:-$HOME/.config}/zim/style.conf -> "${_DST_DIR}/Data/Config/zim/style.conf" ## Copy the config file by converting LF to CR/LF test -f ${XDG_CONFIG_HOME:-$HOME/.config}/zim/style.conf && sed 's/$/\r/' ${XDG_CONFIG_HOME:-$HOME/.config}/zim/style.conf >"${_DST_DIR}/Data/Config/zim/style.conf" ## Create the header of "${_DST_DIR}/Data/Config/zim/notebooks.list" ## with first notebook provided in args as default one echo -en "[NotebookList]\r\nDefault=~/Notebooks/$1\r\n" >${_TEMP_DIR}/notebooks.list.0 ## 2/4 - Remove any existing target notebook that is not in args find "${_DST_DIR}/Data/Notebooks" -mindepth 1 -maxdepth 1 -type d | while read _THE_DIR; do echo $@ | grep -Eq "\<${_THE_DIR##*/}\>" || rm -rf "${_THE_DIR}" done ## 3/4 - rsync each notebook provided in args while test -n "$1"; do test -d "${_SRC_DIR}/$1" || _ERROR=$(( 10 + ${_NOTEBOOK_NR} )) ## Stop rsync loop at first error test ${_ERROR} -ne 0 && break ## Add to the header of future file "${_DST_DIR}/Data/Config/zim/notebooks.list" echo -en "~/Notebooks/$1\r\n" >>${_TEMP_DIR}/notebooks.list.0 ## Add the current notebook to the file "${_DST_DIR}/Data/Config/zim/notebooks.list" echo -en "[Notebook]\r\nuri=~/Notebooks/$1\r\nname=$1\r\ninterwiki=None\r\nicon=None\r\n\r\n" >>${_TEMP_DIR}/notebooks.list.${_NOTEBOOK_NR} ## rsync "${_SRC_DIR}/$1" into "${_DST_DIR}/Data/Notebooks" ## Note: --modify-window=1 is required for FAT target eval rsync ${_VERBOSE} --recursive --times --delete-after --modify-window=1 --filter=\"exclude notebook.zim\" \"${_SRC_DIR}/$1\" \"${_DST_DIR}/Data/Notebooks\" ## "${_SRC_DIR}/$1.txt" -> "${_DST_DIR}/Data/Notebooks/$1.txt" test -f "${_SRC_DIR}/$1.txt" && cp -u "${_SRC_DIR}/$1.txt" "${_DST_DIR}/Data/Notebooks/$1.txt" ## "${_SRC_DIR}/$1/notebook.zim" -> "${_DST_DIR}/Data/Notebooks/$1/notebook.zim" if test -f "${_SRC_DIR}/$1/notebook.zim"; then ## Copy the config file by converting LF to CR/LF, ## disabling hard disk trash can and hard disk buffer sed 's/$/\r/' "${_SRC_DIR}/$1/notebook.zim" >"${_DST_DIR}/Data/Notebooks/$1/notebook.zim" sed -i '/^\(shared\|disable_trash\)=/d' "${_DST_DIR}/Data/Notebooks/$1/notebook.zim" sed -i '/^\s*$/,$h;/^\s*$/d' "${_DST_DIR}/Data/Notebooks/$1/notebook.zim" echo -en "shared=False\r\ndisable_trash=True\r\n\r\n" >>"${_DST_DIR}/Data/Notebooks/$1/notebook.zim" else ## Create the file "${_DST_DIR}/Data/Notebooks/$1/notebook.zim" echo -en "[Notebook]\r\nversion=${_CONFIG_VER}\r\nname=$1\r\ninterwiki=\r\nhome=$1\r\nicon=\r\ndocument_root=\r\nendofline=unix\r\nprofile=\r\nshared=False\r\ndisable_trash=True\r\n\r\n" >"${_DST_DIR}/Data/Notebooks/$1/notebook.zim" fi shift _NOTEBOOK_NR=$(( ${_NOTEBOOK_NR} + 1 )) done ## 4/4 Create the file "${_DST_DIR}/Data/Config/zim/notebooks.list" echo -en "\r\n" >>${_TEMP_DIR}/notebooks.list.0 cat ${_TEMP_DIR}/notebooks.list.* > "${_DST_DIR}/Data/Config/zim/notebooks.list" rm -rf ${_TEMP_DIR} return ${_ERROR} }
Suppose you have to work on a foreign PC running on a debian based GNU/Linux and you want to read your IT knowledge base stored within a Zim Destkop Windows portable with the use of the Zim python sources…
The BASH script (fr) I have written turns an unpacked source Zim tarball into a Debian based GNU/Linux portable that works with Zim Windows portable notebooks. To do that, the following tasks are performed:
--standalone
has refused it (old zim versions), re-execute without that gui option)
That script was tested on Debian 7, Devuan 1 alpha 2 and Ubuntu 14.04.
The debian depend packages are: coreutils, bash, findutils, grep, sed, gawk, python (<3), python-gtk2, python-gobject, python-xdg, xdg-utils
Feel free to use and fork it.
In addition to the technical specifications introduced in paragraph "Zim Desktop portability considerations", that script pays heed to the following Zim properties:
--standalone
do not take precedence over preferences.confHere is the typical file layout for that script to run:
root of USB stick/ ├── PortableApps/ │ └── ZimDesktopWikiPortable/ └── sh/ ├── zim-0.xx/ └── that_script.sh
Usage assuming we call that script zim_linux_portable.sh:
zim_linux_portable.sh [-f|-g WxH+X+Y] [-h] [-s] Options : -f : start Zim portable with option '--fullscreen' -g WxH+X+Y : start Zim portable with option '--geometry args' example: -g 600x600+150+150 (default: '-g 700x500+100+100') -h : print this help and exit -s : start Zim Desktop Linux Portable with option '--standalone'
#!/bin/bash SCRIPTNAME="${0##*/}" SCRIPTDIR="$(readlink -f "${0%/*}")" SCRIPTVERSION="1.0.0" AUTHOR="Médéric" RELEASE_DATE="2015" LICENCE="GPLv3" FRIENDLY_TASK="Launch Zim Desktop Windows Portable within a Linux context" WELCOME="$SCRIPTNAME v.$SCRIPTVERSION by $AUTHOR ($RELEASE_DATE)" ## @author Médéric http://aide.ordi49.fr/wiki/contact-me.html ## Licence: GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html ## THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY ## APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT ## HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY ## OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, ## THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ## PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM ## IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ## ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ## Tested on Debian 7, Devuan 1 alpha 2, Ubuntu14.04 ## Other variables GEOMETRY_DEFAULT="--geometry 700x500+100+100" ## That script aims to launch a Zim linux portable program on a computer ## where zim package is not installed, in order to read the zim notebooks ## that reside within a Windows ZimDesktopWikiPortable USB stick ## That script was writen for debian and devuan GNU/Linux distribution, ## but it should run on any other debian based system ## Feel free to adapt and fork it at your convenience ## Debian depends: coreutils, bash, findutils, grep, sed, gawk, ## python (<3), python-gtk2, python-gobject, python-xdg, xdg-utils ## If one package of the second line is missing, an error is output ## telling the user that it is not installed ## That script can reside within a 1 level-max sub-directory of the USB stick ## (for example a subdir called sh/) or within the root of it ## The Zim linux source directory (downloaded from http://zim-wiki.org/downloads/) ## is supposed to reside within the same or a sub-directory of the script ## The ZimDesktopWikiPortable/Data/Config directory is supposed to reside ## somewhere on the USB stick ## Typical file layout for that script to run: ## root of USB stick/ ## ├── PortableApps/ ## │ └── ZimDesktopWikiPortable/ ## └── sh/ ## ├── zim-0.xx/ ## └── that_script.sh ## How it runs: ## 1. Check for package depends installation ## 2. Check for paths : ## - Path to the most recent python2 ELF found within /usr/bin ## - Path to the most recent zim.py found within the script directory ## - Path to ZimDesktopWikiPortable/Data/Config found next to the script directory ## 3. Convert on the fly the config files of ZimDesktopWikiPortable to a portable linux context ## (EOL are converted from CRLF to LF. In the file notebooks.list, ## the notebook paths are converted to match the linux ones. ## In the file preferences.conf, TrayIconPlugin is disabled if the standalone option is requested. ## In the files notebook.zim, options are set: shared=False and disable_trash=True) ## 4. Execute python 2.X with zim.py script within a special environment. ## (If the standalone option was requested and the script executed with the gui option ## --standalone has refused it (old zim versions), re-execute without that gui option) ## 5. Wait for all processes of zim.py to terminate ## 6. Convert the config files of ZimDesktopWikiPortable back to a portable Windows context ## (EOL are converted from LF to CRLF and in the file notebooks.list, ## the path of the notebooks are converted to match the portable Windows ones. ## Original files preferences.conf and notebook.zim are restored) ## ____ Functions ____ function print_usage() { ## Depends: global variables SCRIPTNAME, GEOMETRY_DEFAULT echo "Usage:" echo "$SCRIPTNAME [-f|-g WxH+X+Y] [-h] [-s]" echo "Options :" echo " -f : start Zim portable with option '--fullscreen'" echo " -g WxH+X+Y : start Zim portable with option '--geometry args'" echo " example: -g 600x600+150+150 (default: '-g ${GEOMETRY_DEFAULT/#--geometry /}')" echo " -h : print this help and exit" echo " -s : start Zim Desktop Linux Portable with option '--standalone'" echo exit } function get_cmd_options() { ## Syntax: ## get_cmd_options $@; test $OPTIND -ne 0 && shift $(($OPTIND - 1)) unset OPTIND local _OPTION while getopts ":fg:hs" _OPTION; do case ${_OPTION} in f) GEOMETRY="--fullscreen";; g) if [[ "$OPTARG" =~ ^[0-9]+x[0-9]+\+[0-9]+\+[0-9]+$ ]]; then GEOMETRY="--geometry $OPTARG" else echo "Wrong value for option -g. Option ignored" >&2 fi ;; h) print_usage; exit;; s) STANDALONE="--standalone";; esac done } function check_zim_depends(){ ## Based on debian package system (dpkg + APT) local _THE_PKG; local _MISSING=( ) ## First depends: python2.X package (X>=6) if test -z "`/usr/bin/dpkg --get-selections | awk '$1~/^python2.[6789][0-9.]*$/{print $1}'`"; then test -x /usr/bin/apt-cache && _MISSING[${#_MISSING[@]}]=`/usr/bin/apt-cache --names-only search python 2>/dev/null | grep -E '^python2\.[6789][0-9.]*\s' | cut -d' ' -f1 | sort | tail -n1` || _MISSING[0]=python2.7 echo "Package ${_MISSING[0]} not installed!" >&2 fi ## Other depends for _THE_PKG in python-gtk2 python-gobject python-xdg xdg-utils; do if ! /usr/bin/dpkg -s ${_THE_PKG} 2>/dev/null | grep -Eiq 'Status:\sinstall\sok\sinstalled'; then echo "Package ${_THE_PKG} not installed!" >&2 _MISSING[${#_MISSING[@]}]=${_THE_PKG} fi done return ${#_MISSING[@]} } function is_running() { ## {path/to/script/or/prog} [/path/to/a/lock/file [drop]] ## Return code is 0 if process is running, 1 if not ## 1st stage validation: is file $1 source of a process running in memory? test -n "`ps -ef | awk '$0!~"awk '$1'" && $0~"'$1'" {print $0}'`" local _RETURNCODE=$? ## 2e stage validation (optional): ## If a lockfile name $2 provided and fist test ok, test presence of $2 if test -n "$2"; then if test ${_RETURNCODE} -eq 0; then test -f "$2" && _RETURNCODE=0 || _RETURNCODE=1 fi ## If the optional lockfile validation fails, it is not usefull either, ## So if $3 say drop, delete its remains test ${_RETURNCODE} -eq 1 -a "$3" == "drop" && rm -f "$2" 2>/dev/null fi return ${_RETURNCODE} } function locate_python_bin() { echo "Searching for python program..." >&2 local _PYTHON_BIN="`find /usr/bin -maxdepth 1 -type f -name python2* | sort | tail -n1`" test -n "${_PYTHON_BIN}" && echo "${_PYTHON_BIN}" || return 9 } function locate_zim_py() { ## Search zim.py into current dir ## (if more than one version, get only the more recent one) echo "Searching for file zim.py..." >&2 local _ZIM_PATH="`find . -type f -name zim.py 2>/dev/null | sort -V | tail -n1`" if test -z "${_ZIM_PATH}"; then echo "Not found!" >&2; return 10 fi if test ! -r "${_ZIM_PATH}"; then if ! chmod +r "${_ZIM_PATH}" 2>/dev/null; then echo "Unable to read: '${_ZIM_PATH}'" >&2; return 11 fi fi readlink -f "${_ZIM_PATH}" } function get_zim_version() { ## {path/to/python_elf} {path/to/zim_py} test -x "$1" -a -f "$1" || return 1 test -f "$2" || return 2 "$1" "$2" -v 2>/dev/null | head -n1 | grep -Eo '[0-9.]+' } function locate_zim_desktop_windows_portable_config() { ## {second_chance_base_search_dir} [first_try_path] echo "Searching for Zim Desktop Windows Portable config dir..." >&2 local _ZIM_CONFIG; local _BASE_DIR="$1" if test -d "$2"; then ## Consider optionnal arg #2 is the good path _ZIM_CONFIG="$2" else ## Perform a deep search from the base directory given by arg #1 test -d "${_BASE_DIR}" || _BASE_DIR=. _ZIM_CONFIG="`find "${_BASE_DIR}" -type d -regex "^.*/ZimDesktopWikiPortable/Data$" | head -n1`" if test -z "${_ZIM_CONFIG}"; then echo "Unable to find ${_BASE_DIR}/ZimDesktopWikiPortable/Data" >&2 return 1 fi _ZIM_CONFIG="${_ZIM_CONFIG}/Config" ## Config dir missing if ZimDesktopWikiPortable never run yet: if test ! -d "${_ZIM_CONFIG}"; then if ! mkdir "${_ZIM_CONFIG}" 2>/dev/null; then echo "Fail to create subdirectory:" >&2 echo "${_ZIM_CONFIG}" >&2 fi fi fi readlink -f "${_ZIM_CONFIG}" } function prepare_files_to_context() { ## [-s] {linux|windows} {ZimDesktopPortableConfigDir} local _ERROR=0 local _CONFIG_VER="0.4" local _STANDALONE=false local _OPTION unset OPTIND while getopts ":s" _OPTION; do case ${_OPTION} in s) _STANDALONE=true;; esac done unset _OPTION test $OPTIND -ne 1 && shift $(($OPTIND - 1)) test -d "$2" || return 1 && local _ZDPCD="$2" ## Zim Desktop Portable Config Dir local _ZDPDD="`readlink -f "${_ZDPCD}/.."`" ## Zim Desktop Portable Data Dir ## 1. Create zim directory if not exists yet if test ! -d "${_ZDPCD}/zim"; then if ! mkdir "${_ZDPCD}/zim" 2>/dev/null; then echo "Unable to create directory:" >&2 echo "${_ZDPCD}/zim" >&2 return 1 fi fi ## 2. Create Notebooks dir if not exists yet if test ! -d "${_ZDPDD}/Notebooks"; then if ! mkdir "${_ZDPDD}/Notebooks" 2>/dev/null; then echo "Unable to create directory:" >&2 echo "${_ZDPDD}/Notebooks" >&2 return 1 fi fi case $1 in linux) ## Prepare the files notebooks.list and .conf to the portable linux context echo "Converting config files to UNIX context..." ## notebooks.list if test -f "${_ZDPCD}/zim/notebooks.list"; then if file -b "${_ZDPCD}/zim/notebooks.list" | grep -q CRLF; then ## Convert file notebooks.list to conform linux context ## Backup existing notebooks.list because it looks like a windows version (CRLF) if ! cp -f "${_ZDPCD}/zim/notebooks.list" "${_ZDPCD}/zim/notebooks.list.winbak" 2>/dev/null; then echo "Fail to backup file notebooks.list" >&2 _ERROR=1 fi ## Convert relative paths of notebooks.list to absolute ones ## (Note: Zim 0.61+ can easily upgrade old style notebooks.list ## into a new one, so convert it in old style without numbered ## notebooks and path if it comes from zim<0.61) sed -i "s:^\(Default\|uri\)=~:\1=file\://${_ZDPDD}:" "${_ZDPCD}/zim/notebooks.list" 2>/dev/null || _ERROR=3 sed -i "s:^\([0-9]\+=\)*~:file\://${_ZDPDD}:" "${_ZDPCD}/zim/notebooks.list" 2>/dev/null || _ERROR=3 ## Convert new style notebook names to old style sed -i "s:^\[Notebook\s\+[0-9]\+\]:[Notebook]:" "${_ZDPCD}/zim/notebooks.list" 2>/dev/null || _ERROR=3 fi else ## Or create a brand new notebooks.list called Notes ## (Note: Zim 0.61+ can easily upgrade old style notebooks.list ## into a new one, so set it in old style without numbered ## notebooks and path if it comes from zim<0.61) echo -en "[NotebookList]\nDefault=file://${_ZDPDD}/Notebooks/Notes\nfile://${_ZDPDD}/Notebooks/Notes\n\n[Notebook]\nuri=file://${_ZDPDD}/Notebooks/Notes\nname=Notes\ninterwiki=None\nicon=None\n\n" >"${_ZDPCD}/zim/notebooks.list" 2>/dev/null || _ERROR=3 ## If not exists, create the file "${_ZDPDD}/Notebooks/Notes/notebook.zim" if test ! -f "${_ZDPDD}/Notebooks/Notes/notebook.zim"; then test -d "${_ZDPDD}/Notebooks/Notes" || mkdir "${_ZDPDD}/Notebooks/Notes" 2>/dev/null || _ERROR=3 echo -e "[Notebook]\nversion=${_CONFIG_VER}\nname=Notes\ninterwiki=\nhome=Notes\nicon=\ndocument_root=\nendofline=unix\nprofile=\n" >"${_ZDPDD}/Notebooks/Notes/notebook.zim" 2>/dev/null || _ERROR=3 fi fi ## preferences.conf: if optional arg -s (standalone) is provided, ## be sure standalone mode is active: do not load trayicon plugin if ${_STANDALONE} && test -f "${_ZDPCD}/zim/preferences.conf"; then ## Backup file preferences.conf and if cp -f "${_ZDPCD}/zim/preferences.conf" "${_ZDPCD}/zim/preferences.conf.winbak" 2>/dev/null; then sed -i '/^\[TrayIconPlugin\]/,/^\s*$/d' "${_ZDPCD}/zim/preferences.conf" 2>/dev/null sed -i '/^\[General\]/,/^\s*$/s/"trayicon",\?//' "${_ZDPCD}/zim/preferences.conf" 2>/dev/null sed -i '/^\[General\]/,/^\s*$/s/,\]/]/' "${_ZDPCD}/zim/preferences.conf" 2>/dev/null fi fi ## Convert all config files from CRLF to LF if file -b "${_ZDPCD}/zim/notebooks.list" | grep -q CRLF; then sed -i 's/\x0D$//' "${_ZDPCD}/zim/notebooks.list" 2>/dev/null || _ERROR=3 fi find "${_ZDPCD}/zim" -type f -name '*.conf' | while read THE_FILE; do file -b "$THE_FILE" | grep -q CRLF && sed -i 's/\x0D$//' "$THE_FILE" 2>/dev/null || _ERROR=3 done ## Files notebook.zim: scan notebook folders searching for notebook.zim, ## secure them against data-leak (shared=False + disable_trash=True) or ## create them if missing sed '/^file:/s/^file:\/\///p;d' "${_ZDPCD}/zim/notebooks.list" | while read THE_PATH; do if test -f "$THE_PATH"/notebook.zim; then ## Disable hard disk trash can and hard disk buffer cp -f "$THE_PATH"/notebook.zim "$THE_PATH"/notebook.zim.linbak 2>/dev/null || _ERROR=3 sed -i '/^\(shared\|disable_trash\)=/d' "$THE_PATH"/notebook.zim 2>/dev/null || _ERROR=3 sed -i '/^\s*$/,$h;/^\s*$/d' "$THE_PATH"/notebook.zim 2>/dev/null || _ERROR=3 echo -e "shared=False\ndisable_trash=True\n" >>"$THE_PATH"/notebook.zim 2>/dev/null || _ERROR=3 else ## notebook.zim not exists: create it echo -e "[Notebook]\nversion=${_CONFIG_VER}\nname=${THE_PATH##*/}\ninterwiki=\nhome=${THE_PATH##*/}\nicon=\ndocument_root=\nendofline=unix\nprofile=\nshared=False\ndisable_trash=True\n" >"$THE_PATH"/notebook.zim 2>/dev/null || _ERROR=3 fi done ;; windows) ## Prepare the files notebooks.list and .conf to the portable windows context echo "Reverting config files to Microsoft Windows context..." ## Notebooks.list if test -f "${_ZDPCD}/zim/notebooks.list"; then if ! file -b "${_ZDPCD}/zim/notebooks.list" | grep -q CRLF; then ## 3.2.1.1. Convert file notebooks.list to conform windows context ## Backup existing notebooks.list because it looks like a linux version (not CRLF) cp -f "${_ZDPCD}/zim/notebooks.list" "${_ZDPCD}/zim/notebooks.list.linbak" 2>/dev/null ## Convert Zim linux portable paths of notebooks back to Zim Windows Portable ones local _RELPATH_FROM_HOME="`echo ${_ZDPDD} | sed "s:^$HOME:~:"`" ## (Note: Zim 0.61+ can easily upgrade old style notebooks.list ## into a new one, so convert it in old style without numbered ## notebooks and path for full compatibility) ## Convert relative linux paths of notebooks back to relative "windows" ones sed -i "s:^\(Default\|uri\)=${_RELPATH_FROM_HOME}:\1=~:" "${_ZDPCD}/zim/notebooks.list" 2>/dev/null || _ERROR=4 sed -i "s:^\([0-9]\+=\)*${_RELPATH_FROM_HOME}:~:" "${_ZDPCD}/zim/notebooks.list" 2>/dev/null || _ERROR=4 ## Convert absolute linux paths of notebooks back to relative "windows" ones sed -i "s:^\(Default\|uri\)=\(file\://\)*${_ZDPDD}:\1=~:" "${_ZDPCD}/zim/notebooks.list" 2>/dev/null || _ERROR=4 sed -i "s:^\([0-9]\+=\)*\(file\://\)*${_ZDPDD}:~:" "${_ZDPCD}/zim/notebooks.list" 2>/dev/null || _ERROR=4 ## Convert new style notebook names to old style sed -i "s:^\[Notebook\s\+[0-9]\+\]:[Notebook]:" "${_ZDPCD}/zim/notebooks.list" 2>/dev/null || _ERROR=4 fi else ## Or create file notebooks.list from previous Windows backup version ## (at that time, EOL must stay LF) if test -f "${_ZDPCD}/zim/notebooks.list.winbak"; then if ! sed 's/\x0D$//' "${_ZDPCD}/zim/notebooks.list.winbak" >"${_ZDPCD}/zim/notebooks.list" 2>/dev/null; then echo "Fail to restore notebooks.list from file:" >&2 echo "${_ZDPCD}/zim/notebooks.list.winbak" >&2 _ERROR=5 fi fi fi ## If optional arg -s (standalone) is provided and ## if preferences.conf was previously backup (for standalone option), restore it if ${_STANDALONE} && test -f "${_ZDPCD}/zim/preferences.conf.winbak"; then test -f "${_ZDPCD}/zim/preferences.conf" && cp -f "${_ZDPCD}/zim/preferences.conf" "${_ZDPCD}/zim/preferences.conf.linbak" 2>/dev/null mv -f "${_ZDPCD}/zim/preferences.conf.winbak" "${_ZDPCD}/zim/preferences.conf" 2>/dev/null fi if test -f "${_ZDPCD}/zim/notebooks.list"; then ## Files notebook.zim: scan notebook folders searching for notebook.zim.linbak grep -E '^(file:|~)' "${_ZDPCD}/zim/notebooks.list" | sed -e 's/^file:\/\///' -e "s:^\([0-9]\+=\)*~:${_ZDPDD}:" | while read THE_PATH; do if test -f "$THE_PATH"/notebook.zim.linbak; then ## Restore previous version to revert secured options (shared= + disable_trash=) cp -f "$THE_PATH"/notebook.zim.linbak "$THE_PATH"/notebook.zim 2>/dev/null || _ERROR=4 else ## notebook.zim not exists: create it echo -e "[Notebook]\nversion=${_CONFIG_VER}\nname=${THE_PATH##*/}\ninterwiki=\nhome=${THE_PATH##*/}\nicon=\ndocument_root=\nendofline=unix\nprofile=\nshared=False\ndisable_trash=True\n" >"$THE_PATH"/notebook.zim 2>/dev/null || _ERROR=4 fi done fi ## Convert all config files from LF to CRLF if ! file -b "${_ZDPCD}/zim/notebooks.list" | grep -q CRLF; then sed -i 's/$/\r/' "${_ZDPCD}/zim/notebooks.list" 2>/dev/null || _ERROR=4 fi find "${_ZDPCD}/zim" -type f -name '*.conf' | while read THE_FILE; do if ! file -b "$THE_FILE" | grep -q CRLF; then sed -i 's/$/\r/' "$THE_FILE" 2>/dev/null || _ERROR=4 fi done ;; *) echo "Config files conversion type not defined" >&2 return 5 ;; esac return ${_ERROR} } ## _____ Main _____ echo $WELCOME echo $FRIENDLY_TASK echo cd "$SCRIPTDIR" ## 1. Analyse command line options get_cmd_options $@ test $OPTIND -ne 0 && shift $(($OPTIND - 1)) test -z "$GEOMETRY" && GEOMETRY="$GEOMETRY_DEFAULT" test -n "$STANDALONE" && STANDALONE_SHORT="-s" || unset STANDALONE_SHORT ## 2. Be sure that all depends are installed check_zim_depends || exit $? ## 3. Locate the python2 ELF PYTHON_BIN="`locate_python_bin`" || exit 9 ## 4. Locate zim.py file ZIM_PY="`locate_zim_py`" || exit 10 ZIM_VERSION="`get_zim_version $PYTHON_BIN "$ZIM_PY"`" || exit 11 echo "Found: Zim Desktop v.$ZIM_VERSION" ## 5. Locate ZimDesktopWikiPortable/Data/Config and set XDG_CONFIG_HOME ## (Note: XDG_CONFIG_HOME should not be equal to $HOME/.config ## because we are not interesting by the personal notebook(s) of the user) ## The script is supposed to be in a subdir of the USB stick (for example sh/), ## and we're not sure Zim Desktop Windows Portable reside into it's native dir. ## So: performs a 2 chances search to find its config path XDG_CONFIG_HOME="`locate_zim_desktop_windows_portable_config .. "../PortableApps/ZimDesktopWikiPortable/Data/Config"`" || exit 12 ## 6. Check for safety operations... ## Problem: ## If another instance is run from "$ZIM_PY", maybe it is from that ## script, or maybe not (direct mouse clic on zim.py) and in that case ## other config files should be used. ## Before to continue, we must be sure that no other instance of zim ## and of that script will modify our portable config files (this could ## lead to ruin them). ## Unfortunately: ## 1. Zim closes config files as soon as read and we cannot lsof them ## 2. Instances of /usr/bin/python2.x is detached (PPID=1) when ## it is executed from Zim (File > Open Another Notebook) ## it is executed from a Windows manager (tested with Openbox) ## So, it's impossible to strickly check (even with a lockfile) and the ## only solution is to exclude any other instance of $ZIM_PY in memory: if is_running "$ZIM_PY"; then ## Alert the user, and stop the script echo echo "Zim instance found in memory from the following zim program:" echo "$ZIM_PY" echo "Please, close that instance before running $SCRIPTNAME again." exit 0 fi ## 7. Convert config files from CRLF to LF and prepare ## the files notebooks.list, notebook.zim and .conf to conform linux context prepare_files_to_context $STANDALONE_SHORT linux "${XDG_CONFIG_HOME}" || exit 13 ## 8. Launch Zim Desktop Linux portable ZIM_STDERR=/tmp/${SCRIPTNAME// /}-${RANDOM}${RANDOM} echo "Launching Zim Desktop Linux portable $ZIM_VERSION..." echo "Do not close this terminal window while Zim is in memory" echo ## Execute Zim with special environment ## Note: Zim 0.63 ignore option --geometry if no other gui option is provided (minor bug?) env XDG_CONFIG_HOME="$XDG_CONFIG_HOME" $PYTHON_BIN "$ZIM_PY" --gui $STANDALONE $GEOMETRY 2>$ZIM_STDERR ## If standalone error (old versions of zim), try without that option if test -n "$STANDALONE" -a -s $ZIM_STDERR && grep -qE "option\s+--standalone\s+not\s+recognized" $ZIM_STDERR; then env XDG_CONFIG_HOME="$XDG_CONFIG_HOME" $PYTHON_BIN "$ZIM_PY" --gui $GEOMETRY 2>$ZIM_STDERR fi ## Print zim stdout if test -s $ZIM_STDERR; then echo "Zim error messages:" >&2 cat $ZIM_STDERR >&2 fi rm -f $ZIM_STDERR ## 9. Wait until all instances of zim has quit memory ## (New instances of zim (others notebooks) are detached from the parent ## (=the first instance). So, if ones closes the first instance, ## the parent script continues but other instances remains in memory) while is_running "$ZIM_PY"; do if test ${ECHOED:-0} -eq 0; then echo echo "Waiting for last instance of zim to end..." ECHOED=1 fi sleep 1 done ## 10. Reverse config files format converting LF to CRLF ## and preparing them to conform to Zim Desktop Windows Portable echo prepare_files_to_context $STANDALONE_SHORT windows "${XDG_CONFIG_HOME}" ERROR=$? case $ERROR in 0) echo "All things done.";; 4) echo "An error occurs in configuration files!" echo "Please, check file notebooks.list before runing this prog again";; esac echo exit $ERROR
${XDG_CONFIG_HOME:-$HOME/.config}/zim
${XDG_DATA_HOME:-$HOME}
but not to $HOME/.local/share
as it is written on the official config files help page%APPDATA%\zim\config\zim
. This conforms to the official config files help page where XDG_CONFIG_HOME defaults to APPDATA/zim/config
APPDATA/zim/data
but Zim Desktop Windows 0.63 stores New notebooks by default into %USERPROFILE%\Notebooks
.%USERPROFILE%
but not to APPDATA/zim/data as it is written on the official config files help page