Skripte/sort recovered

Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:

  1. Einen Terminal öffnen

Inhaltsverzeichnis
  1. Funktionsweise
  2. Quellcode
  3. Skript-Aufruf
  4. Optionen
    1. Dateityp
    2. Größe
    3. PDF-Dateien
    4. Protokollformat
    5. Hilfe
    6. Version
  5. Links

Wiki/Icons/terminal.png Wer schon einmal Daten retten musste, kennt das Problem: Zunächst ist man froh, die Daten wieder zu haben, doch sogleich steht man vor einem Haufen von Verzeichnissen mit völlig unsortierten und nur dem Namen nach durchnummerierten Dateien. Hier setzt das Bash-Skript sort_recovered.sh an, dass die Dateien nach Datei-Erweiterungen umsortiert.

Funktionsweise

Das Skript durchsucht das Verzeichnis, in welchem die wiederhergestellten Dateien liegen, ermittelt deren Erweiterung, erstellt im Ziel-Verzeichnis pro Erweiterung ein Unterverzeichnis und kopiert die Dateien dann ihrer Erweiterung entsprechend in das zugehörige Unterverzeichnis. Die Dateien werden dabei kopiert und nicht umbenannt, so dass das Quellverzeichnis in seiner Original-Struktur erhalten bleibt.

Die Sortierung lässt sich dabei auf Dateien mit nur bestimmter Erweiterung und/oder bestimmter Größe einschränken sowie beliebig oft wiederholen.

Der jeweilige Durchlauf wird in der Datei $HOME/Sort_Recovered/sort_recovered_log[n].txt protokolliert.

Quellcode

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
#!/bin/bash
version="0.6"
versionDate="26.11.2011"

# Hilfetext
function usage() {
	cat <<EOF

Beschreibung:
Kopiert Dateien aus einem Recovery-Verzeichnis nach Datei-Erweiterung sortiert
in entpsrechende Unterverzeichnisse des Ziel-Verzeichnises. Die Sortierung kann
auf bestimmte Erweiterungen und bestimmte Dateigrößen eingeschränkt werden.


Befehls-Syntax:
$scriptname <Recovery-Verzeichnis> <Ziel-Verzeichnis> [-type <Dateierweiterung>
-size <Dateigröße> -query-pdf -logformat <Format>]

Pflichtangaben:

<Recovery-Verzeichnis>	Pfad zum Verzeichnis, in dem sich die Verzeichnisse mit
			wiederhergestellten bzw. gefundenen Dateien befinden.

<Ziel-Verzeichnis>	Pfad zum Verzeichnis, in das die gefundenen Dateien nach
			Erweiterung einsortiert werden sollen.
Optionen:
-type	Dateierweiterung(en) der Dateien, nach den in den wiederhergestellten
	Dateien gesucht und sortiert werden soll.
			
	Es können mehrere Erweiterungen angegeben werden, wobei	eine Liste mit
	Erweiterungen in Anführungszeichen ("") eingeschlossen werden muss.

	Wird "auto" angegeben, so werden die Erweiterungen der Dateien automa-
	tisch ermittelt und entsprechend in das Ziel-Verzeichnis einsortiert.
	"auto" ist auch	die Standardeinstellung, falls type nicht angeben wird.

	Beispiele:
	-type jpg
	-type "jpg mp3 ogg"
	-type auto

-size	n[cbwkMG] Größenangabe oder ein Größenbereich der für die Sortierung
	berücksichtigt werden soll. Bei einem Bereich müssen die Angaben in
	Anführungszeichen ("") eingefasst werden.
	
	Folgende Einheiten können angegeben werden:

	c 	für Byte
	b 	für 512 Byte-Blöcke
        w       für 2 Byte Wörter
	k 	für Kilobyte (Einheit von 1024 Byte)
	M 	für Megabyte (Einheit von 1048576 Byte)
	G 	für Gigabyte (Einheit von 1073741824 Byte)

	Beispiele:
	-size 550k	nur Dateien, die 550 k-Einheiten groß sind.
	-size -2G	nur Dateien, kleiner als 2 G-Einheiten sind.
	-size +500M	nur Dateien, größer 500 M-Einheiten.
	-size "+5M -9M"	Dateien größer 5 M-Einheiten und kleiner 9 M-Einheiten.


-query-pdf	Wird diese Option gesetzt so werden mittels "pdfinfo" Titel
		aus den Meta-Daten des PDF-Dokuments ermittelt und sofern
		der Titel nicht leer ist, als Ergebnis in eine Text-Datei
		geschrieben.

-logformat	<Format> kann "unix" oder "windows" sein. Standardwert ist 
		"unix". Bei "windows" wird am Ende jeder Zeile einer Ergeb-
		nisdatei ein <CR> eingefügt, wodurch sich die Textdateien
		dann auch von Windows aus übersichtlich lesen lassen.

-v --version	Zeigt die Version dieses Skriptes an.

-h --help	Zeigt diesen Hilfe-Text an.
EOF
}

#
# Historie
#
# Version 0.6 vom 26.11.2011
# - Bugfix: "find: unbekannte Option `-size" beseitigt.
# - Bugfix: "Zeile 142: processcopy_Files_ext: Kommando nicht gefunden." beseitigt.
# - Bugfix: Eventuell auftretende Probleme mit Leerzeichen in Datei-Namen beseitigt.
#
#
# Version 0.5 vom 07.04.2011
# - erste veröffentlichte Version
#

# -size Option auswerten. Die Werte sind an die von "find" (siehe "man find")
# angekoppelt.
function check_size() {
	string=$1
	Message="-size Option: $string...ok"
	case ${string:(-1)} in
		[0-9] | b )
			sizeSuffix="512 Byte-Blöcke"
			divisor=512;;
		c )
			sizeSuffix="Byte"
			divisor=1;;
		G )
			sizeSuffix="G"
			divisor=1073741824;;
		k )
			sizeSuffix="k"
			divisor=1024;;
		M )
			sizeSuffix="M"
			divisor=1048576;;
		w )
			sizeSuffix="2 Byte-Wort"
			divisor=2;;
		* )
			Message="FEHLER: -size Angabe entspricht nicht den syntaktischen Vorgaben."
			exit 1;;
	esac
	echo_toScrnLog "$Message"
}

# Ermittelt die Dateierweiterung, der an $1 übergebenen Datei
# Speichert eine Liste der bisher verarbeiteten Erweiterungen
# in der Feld-Variablen $processedExtensions
function get_extension () {
	file="$1"
	extension=$(echo "$file"| awk -F . '{if (NF>1) {print $NF}}')
	if [ -z "$extension" ]; then
		extension="NONE"
	fi
	case "${processedExtensions[@]}" in
		*"$extension"*);;
		*)
			processedExtensions=("${processedExtensions[@]}" "$extension");;
	esac
}

# Ermittel abhängig von den Optionen -type und -size, die Art des Kopiervorgangs.
# Die Optionen werden über die Variable $parameter aus dem Hauptlauf an $1 zuge-
# wiesen.
function copy_files() {
	IFSbak=$IFS
	IFS=$'\n'
	case $1 in
		auto )
			cp "$path/$file" "$fulltargetDir/$file" && cpfileCount=$((cpfileCount+1)) && totalSize=$((totalSize+$(stat -c%s "$file")))
			;;	
		auto_size )
			case $sizeSet in
				1 )
					copyFiles=$(find -maxdepth 1 -name "$file" -size $size1 -type f);;
				2)
					copyFiles=$(find -maxdepth 1 -name "$file" -size $size1 -size $size2 -type f);;
			esac
			process_copyFiles_auto
			;;
		ext )
			copyFiles=$(find -maxdepth 1 -name "*.$extension" -type f)
			process_copyFiles_ext
			;;
		ext_size )
			case $sizeSet in
				1 )
					copyFiles=$(find -maxdepth 1 -name "*.$extension" -size $size1 -type f);;
				2 )
					copyFiles=$(find -maxdepth 1 -name "*.$extension" -size $size1 -size $size2 -type f);;
			esac
			process_copyFiles_ext
			;;
	esac
	IFS=$IFSbak
}

function process_copyFiles_ext() {
	for file in ${copyFiles[@]};
	do
		cp "$file" "$fulltargetDir/$file" && cpfileCount=$((cpfileCount+1)) && totalSize=$((totalSize+$(stat -c%s "$file")))
		eval $MSG_pcpStatus
	done	
}

function process_copyFiles_auto() {
	for file in ${copyFiles[@]};
	do
		cp "$file" "$fulltargetDir/$file" && cpfileCount=$((cpfileCount+1)) && totalSize=$((totalSize+$(stat -c%s "$file")))
	done	
}

# Ergebnisse des Umkopierens zusammentragen
function query_Results() {
	print_toScr "Trage Ergebnisse zusammen..."
	if [ "$type" == "auto" ];
	then
		processedExtensions=$(echo "${processedExtensions[@]}" |tr " " "\n"|sort|tr "\n" " ")
		for extension in $processedExtensions;
		do
			newstring=$extension
			if [ ${#extension} -gt 8 ];
			then
				shorten_Extension
			fi
			if [ "$newstring" != "$extension" ];
			then
				if [ -d "$targetDir/$newstring" ];
				then
					rm -R "$targetDir/$newstring"
				fi
				mv "$targetDir/$extension$sizeLable" "$targetDir/$newstring$sizeLable"
				extension=$newstring
			fi
			fulltargetDir="$targetDir/$extension$sizeLable"
			fileCount=$(ls -1 "$fulltargetDir" | wc -l)
			remove_emptytargetDir
		done
	else
			fileCount=$(ls -1 "$fulltargetDir" | wc -l)
			remove_emptytargetDir
	fi		
}

# Dateierweiterungen, in denen sich das selbe Zeichen vier mal oder mehr wieder-
# holt, kürzen. Das betreffende Zeichen wird nur einmal ausgegeben und dahinter 
# der Wert der Wiederholung. Beispiel:
# "exe____________" wird zu "exe_(12)"
function shorten_Extension() {
	string=$extension
	for character in $(echo $extension | sed 's/\(.\)/\1\n/g');
	do
		case "$processedCharacters" in
			*"$character"*);;
			*)
				processedCharacters="$processedCharacters $character"
				strangestring=$(echo "$extension" | grep -o "\($character\{4,\}\)")
				charcount="${strangestring//[^$character]/}"
				newstring=$(echo $string | sed "s/$character\{4,\}/$character\(${#charcount}\)/")
				string=$newstring
				;;
		esac
	done
}

#Im Zielverzeichnis angelegte Verzeichnisse, die keine Dateien enthalten löschen
function remove_emptytargetDir() {
	case $fileCount in
		0 )				
			rm -R "$fulltargetDir";;
		* )
			get_dirSize;;
	esac
}

# Die Größe eines Verzeichnisses ermitteln
function get_dirSize() {
	dirSize=0
	cd "$fulltargetDir"
	for file in *;
	do
		dirSize=$((dirSize+$(stat -c%s "$file")))
	done
	formatnsave_resultVars
}

# Die Resultate für die Tabellen-Auflistung formatieren
function formatnsave_resultVars() {
	dirSize=$((dirSize/$divisor))
	dirSize=$(echo -e "$dirSize" | sed  -e :a -e 's/^.\{1,12\}$/ & /;ta')
	fileCount=$(echo -e "$fileCount" | sed  -e :a -e 's/^.\{1,19\}$/ & /;ta')
	IFSbak=$IFS
	IFS=$'\n'
	cpResults[${#cpResults[*]}]=$(echo -e "$extension\t\t$fileCount\t\t$dirSize")
	IFS=$IFSbak

}

# Vom Skript erzeugte Text-Dateien mit <CR> am Zeilen-Ende ergänzen
function change_LOGS_toWin() {
	cd "$workDir"
	for log in *;
	do
		if [ -f $log ];
		then
			awk '{printf("%s\r\n",$0)}' $log > "win-$log"
		fi
	done
}

# Sofern PDF-Dateien vorhanden sind, diese nach ausgefüllten Titel-Einträgen
# mittels pdfinfo durchsuchen und die gefundenen Titel in die Datei
# "FoundPDFTitle.txt" zusammen mit dem Titel schreiben. PDFs ohne Titel werden
# in der Datei "FoundPDFnoTitle.txt" gelistet. PDFs, die von pdfinfo nicht ver-
# arbeitet werden konnten werden in "PDFqueryError.txt" aufgeführt.
function query_PDF_Title() {
	print_toScrnLog "Suche nach PDF-Titeln..."
	PDFTitles=$workDir/FoundPDFTitle.txt
	PDFnoTitles=$workDir/FoundPDFnoTitle.txt
	queryERROR=$workDir/PDFqueryError.txt
	tmpqueryERROR=$workDir/tmpError.txt
	errorCount=0
	PDFTitleCount=0
	PDFnoTitleCount=0
	processedPDFCount=0
	if [ -d "$targetDir/pdf" ];
	then
		cd "$targetDir/pdf"
		for file in *;
		do
			Title=""
			pdfinfoResult=$($pdfinfo "$file" 2>$tmpqueryERROR) 
			pdfError=$?
			Title=$(echo "$pdfinfoResult" | grep ^Title: | sed 's/^Title://' | tr -s " " | sed 's/^.//')
			case $pdfError in
				0 )
					if [ "$Title" == "" ];
					then
						echo -e "$file\t$Title" >> $PDFnoTitles
						PDFnoTitleCount=$((PDFnoTitleCount+1))
					else
						echo -e "$file\t$Title" >> $PDFTitles
						PDFTitleCount=$((PDFTitleCount+1))
					fi;;
				* )
					tmpError=$(tail $tmpqueryERROR)					
					errorCount=$((errorCount+1))
					echo -e "$file\t$tmpError" >> $queryERROR
					echo >> $queryERROR
					pdfErrorStatus=1;;
			esac
			processedPDFCount=$((PDFCount+1))
			echo -ne "PDFs: $PDFCount\tTitel:$PDFTitleCount\tohne Titel: $PDFnoTitleCount\tFehler: $errorCount"\\r
		done
	else
		echo_toScrnLog "Es wurden keine PDF-Dateien im Ziel-Verzeichnis gefunden."
	fi
	case $pdfErrorStatus in
		0 )
			echo_toScrnLog "ohne Fehler abgeschlossen.\n";;
		1 )
			echo_toScrnLog "mit $errorCount Fehlern abgeschlossen.\n\nSiehe $queryError";;
	esac
	if [ -e "$tmpqueryERROR" ];
	then
		rm -f "$tmpqueryERROR"
	fi
}

# Alle Unterverzeichnisse des Recovery-Verzeichnisses ermitteln und in der Feld-
# variable $DIRS speichern
function get_DIRS() {
	cd "$recoverDir"
	IFSbak=$IFS
	IFS=$'\n'
	DIRS=($(find "." -maxdepth 1 -mindepth 1 -type d))
	dirCount=${#DIRS[@]}
	IFS=$IFSbak
	for (( index=0; index<${dirCount}; index++ ));
	do
		IFSbak=$IFS
		IFS=$'\n'
		files=($(find "${DIRS[$index]}" -maxdepth 1 -mindepth 1 -type f))
		dirfileCount=${#files[@]}
		IFS=$IFSbak
		totalfileCount=$((totalfileCount+$dirfileCount))
	done
	print_toScrnLog "abgeschlossen.\n"
	echo_toScrnLog "Es wurden $dirCount Verzeichnisse mit insgesamt $totalfileCount Dateien gezählt."
}

function print_toScrnLog() {
	printf "$1" | tee -a $LOG
}

function print_toScr() {
	printf "$1"
}

function echo_toScr() {
	echo "$1"
}

function echo_toScrnLog() {
	echo "$1" | tee -a $LOG	
}

function echo_toLog() {
	echo $1 >> $LOG
}

# Schreibrechte des Benutzers im Ziel-Verzeichnis prüfen
function check_permission() {
	error=$(mkdir "$targetDir" 2>&1)
	if [[ "$error" == "" ]]; then
		rm -R "$targetDir"
		return 0
	elif [[ "$error" =~ "$permError" ]]; then
		echo_toScrnLog "FEHLER: Keine Schreib-Berechtigung für Ziel-Verzeichnis."
		exit 1
	else
		echo_toScrnLog "FEHLER: $error"
		exit 1
	fi
}

# Den Dateinamen dieses Skriptes ermitteln
function get_scriptname() {
	scriptname=$(echo $0 | awk -F / '{print $NF}')
}

# Den Namen der Portokoll-Dateien festlegen
function set_LOG() {
	LogFile="${workDir}/sort_recovered_log"
	rotationCounter=0
	while ( [ -e "${LogFile}${rotationCounter}.txt" ] )
	do 
		rotationCounter=$((rotationCounter+1))
		wait
	done
	LOG="${LogFile}${rotationCounter}.txt"
	cpRESULT="${workDir}/cpRESULT.txt"
}

# Arbeitsverzeichnis unter $HOME anlegen
function set_workdir() {
	workDir="$HOME/Sort_Recovered"
	[ ! -d "$workDir" ] && mkdir "$workDir"
}


################################## Hauptlauf ##################################

recoverDir=""
targetDir=""
echo

# Name des Skriptes ermitteln
get_scriptname

#Versionsinformationen ausgeben.
if [ "$1" == "-v" -o "$1" == "--version" ];
then
	echo_toScr "$scriptname\nVersion: $version\nDatum:\t $versionDate\n"
	exit 0
fi

# Arbeitsverzeichnis und Logdatei setzen
set_workdir
set_LOG


#Skriptaufruf und Parameter prüfen:

# Falls gar nichts mit dem Skriptaufruf übergeben wurde
if [ "$1" == "" ];
then
	echo_toScrnLog "FEHLER: Verzeichnis-Angaben fehlen!"
	usage
	exit 1
fi

# Prüfen, dass erste Angabe ein vorhandenes Verzeichnis ist
print_toScrnLog "Prüfe Recovery-Verzeichnis..."
if [ -d "$1" ];
then
	recoverDir="$1"
	print_toScrnLog "Gefunden!\n"
else

	echo_toScrnLog "FEHLER: Das angegebene Recovery-Verzeichnis "$1" existiert nicht!"
	usage
	exit 1
fi

# Prüfen, dass zweite Angabe übergeben wurde
shift
if [ "$1" == "" ];
then
	echo_toScrnLog "FEHLER: Es wurde kein Ziel-Verzeichnis angegeben!"
	usage
	exit 1
fi

# Prüfen, dass zweite Angabe ein bestehendes Verzeichnis ist und Verzeichnis
# erstellen, falls es nicht existiert
print_toScrnLog "Prüfe Ziel-Verzeichnis..."
if [ -d "$1" ];
then
	targetDir="$1"
	if [ -w "$targetDir" ]; then
		print_toScrnLog "gefunden! Schreibberechtigung besteht.\n"
	else
		echo_toScrnLog "FEHLER: Keine Schreib-Berechtigung für Ziel-Verzeichnis."
		exit 1
	fi
else
	eval $MSG_targetDirnotexist
	targetDir="$1"
	check_permission
	mkdir "$targetDir" && print_toScrnLog "erfolgreich.\n"
fi

# Standardwerte für den Fall setzen, dass Optionen nicht angegeben sind:
type="auto"
sizeSet=0
sizeLable=""
sizeSuffix="k"
divisor=1024	
logFormat="unix"
queryPDF="NO"

# Optionen prüfen
shift
echo_toScrnLog "Prüfe Skript-Parameter..."
echo >> $LOG
	while [ "$1" != "" ];
	do
		Option="$1"
		case $1 in
			-h | --help )
				usage
				exit 0;;
			-type )
				shift
				type=$1
				echo_toLog "Überprüfe -type-Parameter...\ntype-Parameter= $type"
				if [ "$type" == "" ];
				then
					echo_toScrnLog "FEHLER: Angabe für Parameter -type fehlt."
					exit 1
				fi
				[ "$type" != "auto" ] && type=$(echo "$type" |tr " " "\n"|sort|tr "\n" " ")
				echo "\$type=$type" >> $LOG
				echo_toLog "...-type-Parameter ok."
				echo >> $LOG;;
			-size )
				shift
				tempsize=$1
				echo_toLog "-size-Parameter wird gepürft..."
				for item in ${tempsize[*]};
				do
					check_size $item					
					if [ $sizeSet == 0 ];
					then
						size1=$item
						sizeLable="$item"
						sizeSet=1
					else
						size2=$item
						sizeLable=$sizeLable"$item"
						sizeSet=2				
					fi
				done
				echo "\$size=-size $size1 -size $size2" >> $LOG
				echo "\$sizeLable=$sizeLable" >> $LOG
				echo_toLog "-size-Parameter ok!"
				echo >> $LOG
				;;
			-logformat )
				shift
				logFormat="$1"
				;;
			-query-pdf )
				if [ ! -e /usr/bin/pdfinfo ];
				then
					echo_toScrnLog "FEHLER: Das für die Suche nach PDF-Titeln notwendige Programm $pdfinfo existiert nicht."
				else
					pdfinfo="/usr/bin/pdfinfo"
					queryPDF=YES
				fi
				;;
			-* )
				echo_toScrnLog "FEHLER: Ungültige Option: $Option"
				usage
				exit 1
				;;
			* )
				usage
				exit 1;;
		esac
		shift	
	done
echo_toScrnLog "...Skript-Parameter ok!"
echo | tee -a $LOG

# Unterverzeichnisse im angegeben Recovery-Verzeichnis ermitteln
print_toScrnLog "Ermittle Unterverzeichnisse in $recoverDir..."
get_DIRS
echo >> $LOG

# Sortiertes Kopieren starten
echo_toScrnLog "Starte Kopiervorgang..."
Starttime=$(date)
echo_toScrnLog "Start: $Starttime"
echo | tee -a $LOG
echo_toScrnLog "Recovery-Verzeichnis: $recoverDir"
echo_toScrnLog "Ziel-Verzeichnis: $targetDir"
IFSbak=$IFS
IFS=$'\n'
cpResults[0]=$(echo -e "Dateityp\t\tAnzahl Dateien\t\tGröße ($sizeSuffix)")
IFS=$IFSbak
totalSize=0
dirCountlocal=0
cpfileCount=0
if [ "$type" == "auto" ];
then
	for (( index=0; index<${dirCount}; index++ ));
	do
		cd "$recoverDir"
		cd "${DIRS[$index]}"
		path=$(pwd)
		dirCountlocal=$((dirCountlocal+1))
		for file in *;
		do
			get_extension "$file"
			if [ $sizeSet == 0 ];
			then
				fulltargetDir="$targetDir/$extension"
				parameter="auto"
			else
				fulltargetDir="$targetDir/$extension$sizeLable"
				parameter="auto_size"
			fi
			if [ ! -d "$fulltargetDir" ]; then
				mkdir "$fulltargetDir"
			fi
			if [ -f "$file" ]; then
				copy_files $parameter
			fi
			echo -ne "Verzeichnisse: $dirCountlocal\tDateien gesamt: $cpfileCount\tDateitypen: ${#processedExtensions[*]}"\\r
		done
	done
#	echo | tee -a $LOG
#	echo_toScrnLog "...Kopiervorgang abgeschlossen."
#	Endtime=$(date)
#	echo_toScrnLog "Ende: $Endtime"
#	echo | tee -a $LOG
#	query_Results

else
	for extension in $type;
	do
		if [ "$sizeLable" == "" ];
		then
			fulltargetDir="$targetDir"/$extension
		else
			fulltargetDir="$targetDir"/$extension$sizeLable
		fi
		if [ ! -d "$fulltargetDir" ];
		then
			mkdir "$fulltargetDir"
		fi
		index=0
		while [ $index -ne $dirCount ];
		do
			cd "$recoverDir"
			cd "${DIRS[$index]}"
			IFSbak=$IFS
			IFS=$'\n'
			if [ $sizeSet == 0 ]; then
				parameter="ext"
			else
				parameter="ext_size"
			fi
			copy_files $parameter
			index=$((index+1))
			IFS=$IFSbak
		done
#>
	done
fi
		echo | tee -a $LOG
		echo_toScrnLog "...Kopiervorgang abgeschlossen."
		Endtime=$(date)
		echo_toScrnLog "Ende: $Endtime"
		echo | tee -a $LOG
		query_Results
#Ergebnisse auswerten und für Tabellenausgabe aufbereiten
totalSize=$((totalSize/$divisor))
totalSize=$(echo -e "$totalSize" | sed  -e :a -e 's/^.\{1,12\}$/ & /;ta')
cpfileCount=$(echo -e "$cpfileCount" | sed  -e :a -e 's/^.\{1,19\}$/ & /;ta')
IFSbak=$IFS
IFS=$'\n'
cpResults[${#cpResults[*]}]=$(echo -e "Gesamt:\t\t$cpfileCount\t\t$totalSize")
echo
OUTPUT=$(
	for line in ${cpResults[@]};
	do
		echo -e "$line"
	done
	)
IFS=$IFSbak
print_toScr "abgeschlossen:\n\n"
echo -e "$OUTPUT" | column -t -s"$(echo -e "\t")" | tee -a $LOG
echo | tee -a $LOG 

# Nach Titeln in PDF-Meta-Daten suchen, falls "-query-pdf" angegeben wurde.
if [ "$queryPDF" == "YES" ];
then
	echo_toScrnLog "Suche nach PDF-Titeln..."
	Starttime=$(date)
	echo_toScrnLog "Start: $Starttime"
	query_PDF_Title
	echo_toScrnLog "...Suche abgeschlossen."
	Endtime=$(date)
	echo_toScrnLog "Ende: $Endtime"
fi

# LOGS in Windows-txt-Format umwandeln, falls "-logformat windows" angegeben wurde.
if [ "$logFormat" == "windows" ];
then
	change_LOGS_toWin
fi

echo
chown $(basename ~) "$LOG"
chown $(basename ~) "$workDir"
if [ "$queryPDF" == "YES" ];
then
	chown $(basename ~) "$PDFTitles"
	chown $(basename ~) "$PDFnoTitles"
	chown $(basename ~) "$queryERROR"
fi


Skript-Aufruf

Das Skript wird wie folgt aufgerufen:

/PFAD/ZUM/SKRIPT/sort_recovered RECOVERY-VERZEICHNIS ZIEL-VERZEICHNIS [OPTIONEN] 

RECOVERY-VERZEICHNIS und ZIEL-VERZEICHNIS sind Pflichtangaben. Dabei muss der vollständige Pfad zum jeweiligen Verzeichniss angegeben werden. Sofern Leerzeichen im Verzeichnis-Pfad enthalten sind, muss die Angabe in Anführungszeichen ("") eingefasst werden. Alle anderen Angaben sind optional. Beispiel:

$HOME/bin/sort_recovered $HOME/testdisk-recover $HOME/sortiert 

Optionen

Dateityp

-type DATEIERWEITERUNG - Dateierweiterung(en) der Dateien, nach den in den wiederhergestellten Dateien gesucht und sortiert werden soll. Es können mehrere Erweiterungen angegeben werden, wobei eine Liste mit Erweiterungen in Anführungszeichen ("") eingeschlossen werden muss.

Wird auto angegeben, so werden die Erweiterungen der Dateien automatisch ermittelt und entsprechend in das Ziel-Verzeichnis einsortiert. auto ist auch die Standardeinstellung, falls -type nicht angeben wird. Beispiele:

-type jpg
-type "jpg mp3 ogg"
-type auto

Größe

-size DATEIGRÖSSE - Größenangabe oder ein Größenbereich, der für die Sortierung berücksichtigt werden soll. Bei einem Bereich müssen die Angaben in Anführungszeichen ("") eingefasst werden.

Folgende Einheiten können angegeben werden:

Argument Bedeutung
c Byte
b 512 Byte-Blöcke
w 2 Byte Wörter
k Kilobyte (Einheit von 1024 Byte). Standardwert, falls -size nicht angegeben.
M Megabyte (Einheit von 1048576 Byte)
G Gigabyte (Einheit von 1073741824 Byte)

Beispiele:

-size 550k	## nur Dateien, die 550 k-Einheiten groß sind.
-size -2G	## nur Dateien, kleiner als 2 G-Einheiten sind.
-size +500M	## nur Dateien, größer 500 M-Einheiten.
-size "+5M -9M"	## Dateien größer 5 M-Einheiten und kleiner 9 M-Einheiten.

Hinweis:

Der Größenvergleich mit den Einheiten ist nicht immer intuitiv. Vergleiche, die nach einem Ergebnis kleiner einer einzigen Einheit suchen - also z.B. -1G - sind nach der Block-Rechnungsweise nämlich gleichbedeutend mit Dateien die kleiner 0 sind, denn nur gar kein Block, also eben 0 ist kleiner als ein 1G Block.

PDF-Dateien

-query-pdf - wird diese Option gesetzt, so werden mittels pdfinfo (siehe man pdfinfo) Titel aus den Meta-Daten des PDF-Dokuments ermittelt und sofern der Titel nicht leer ist, als Ergebnis in eine Text-Datei geschrieben.

Protokollformat

-logformat FORMAT - legt das Format für die Protokoll- und Ergebnis-Dateien fest. FORMAT kann unix oder windows sein. Standardwert ist unix. Bei windows wird am Ende jeder Zeile einer Ergebnisdatei ein <CR> eingefügt, wodurch sich die Textdateien dann auch unter Windows übersichtlich lesen lassen.

Hilfe

-h oder --help - zeigt einen Hilfe-Text für das Skript an.

Version

-v oder --version - zeigt die Version des sort_recovered-Skriptes an.