спасибо за отличные ответы! Я реорганизовал свой скрипт, и он работает неплохо :)
Вот отремонтированный, улучшенный код с протоколированием, параметрами и еще кое-чем. Я всегда открыт для улучшения своего кода. Заранее спасибо.
#!/bin/bash
## Script to compress PDF Files using ghostscript incl. subdirs
## Copyright (C) 2016 Maximilian Fries - All Rights Reserved
## Contact: maxfries@t-online.de
## Last revised 2016-07-29
# Usage
# ./pdf-compress.sh [screen|ebook|prepress|default] [verbose]
# Variables and preparation
{
count=0
success=0
successlog=./success.tmp
gain=0
gainlog=./gain.tmp
pdfs=$(find ./ -type f -name "*.pdf")
total=$(echo "$pdfs" | wc -l)
log=./log
verbose="-dQUIET"
mode="prepress"
echo "0" | tee $successlog $gainlog > /dev/null
}
# Are there any PDFs?
if [ "$total" -gt 0 ]; then
#Parameter Handling & Logging
{
echo "-- Debugging for Log START --"
echo "Number of Parameters: $#"
echo "Parameters are: $*"
echo "-- Debugging for Log END --"
} >> $log
# Only compression-mode set
if [ $# -eq 1 ]; then
mode="$1"
fi
# Also Verbose Level Set
if [ $# -eq 2 ]; then
mode="$1"
verbose=""
fi
echo "$pdfs" | while read -r file
do
((count++))
echo "Processing File #$count of $total Files" | tee -a $log
echo "Current File: $file "| tee -a $log
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS="/$mode" -dNOPAUSE \
-dBATCH $verbose -sOutputFile="$file-new" "$file" | tee -a $log
sizeold=$(wc -c "$file" | cut -d' ' -f1)
sizenew=$(wc -c "$file-new" | cut -d' ' -f1)
difference=$((sizenew-sizeold))
# Check if new filesize is smaller
if [ $difference -lt 0 ]
then
rm "$file"
mv "$file-new" "$file"
printf "Compression was successfull. New File is %'.f Bytes smaller\n" \
$((-difference)) | tee -a $log
((success++))
echo $success > $successlog
((gain-=difference))
echo $gain > $gainlog
else
rm "$file-new"
echo "Compression was not necessary" | tee -a $log
fi
done
# Print Statistics
printf "Successfully compressed %'.f of %'.f files\n" $(cat $successlog) $total | tee -a $log
printf "Safed a total of %'.f Bytes\n" $(cat $gainlog) | tee -a $log
rm $successlog $gainlog
else
echo "No PDF File in Directory"
fi
Я нашел способ. Я взял его с какого-то сайта stackexchange, но не могу найти его обратно.
В любом случае: Вы можете злоупотреблять опцией bash --init-file
. Она предназначена для отмены использования другого стартового скрипта вместо .bashrc, но вы можете поместить туда что угодно. В сочетании с анонимными трубами вы можете сделать примерно следующее:
bash --init-file <(echo "your --command --here")
После завершения команды вы будете возвращены в bash - не в новый экземпляр bash, как в некоторых других решениях, а в тот же самый экземпляр.
Конечно, при этом будет пропущен .bashrc, потому что именно для этого предназначен --init-file
. Чтобы исправить это, вы получите потрясающе красивый
bash --init-file <(echo ". \"$HOME/.bashrc\"; your --command --here")
Уродливый, но он работает :-)
О подсистеме Windows для Linux
Наконец, я попробовал сделать это из Windows, но попал в беду, потому что когда вы запускаете bash
, чтобы вызвать подсистему Windows для Linux, вы все еще находитесь в стране Windows, поэтому анонимные трубы не будут работать, $HOME будет неправильным, и так далее. Моим обходным решением для "cmd /k, но для запуска подсистемы windows для linux" стало:
bash -c 'exec bash --init-file ^<(echo ". \"$HOME/.bashrc\"; your --command --here")'
Обратите внимание на ^
, чтобы убрать символ <
. Это запустит bash (bash -c
), немедленно заменит текущий процесс bash на новый (exec
), который также является процессом bash, теперь инициализированным, как обсуждалось ранее, из "Linux land".
Я сделал пакетный файл под названием bash-k.cmd
в моем PATH, чтобы я мог легко вызвать его, с этим внутри:
@bash -c 'exec bash --init-file ^<(echo ". \"$HOME/.bashrc\"; %*")'
Это позволяет мне сделать bash-k cowsay hello
и все будет работать