2016-07-11 3 views
1

Ich mag Dateien kopieren, die in einem anderen Ordner 100 Zeilen oder mehr:Wie Dateien zu kopieren, die Zeilennummer> 100 auf andere Ordner mit

$ cd "/home/john/folder a" 
$ wc -l * 
10 file1.txt 
50 file2.txt 
100 file3.txt 
150 file4.txt 

I Datei file3.txt und file4.txt (Dateien kopieren mag, dass mit 100 Zeilen oder mehr) zum Ordner /home/john/folder b.

Kann mir bitte jemand helfen? Vielen Dank.

Antwort

2

Try this:

declare -i numfile 
for f in *; do 
    numfile=$([ -f "$f" ] && cat "$f" | wc -l) 
    [ $numfile -ge 100 ] && cp "$f" otherdir 
done 

Für jede Dateien im aktuellen Verzeichnis wird numfile die Anzahl der Zeilen der Datei zugeordnet.

Wenn numfile größer oder gleich 100 ist, wird die Datei nach otherdir kopiert.

Edit:

Als William Pursell erwähnt, ein robuster Ansatz zu testen wäre, wenn das Element ein Dateivergleich Ausführung vor ist und kopieren Befehle:

for f in *; do 
    if [ -f "$f" ]; then 
    [ "$(wc -l < $f)" -ge 100 ] && cp "$f" otherdir; 
    fi 
done 
+0

Ich nehme an, Ihre Antwort ist definitiv mehr auf den Punkt als meine :) – Will

+0

Verlassen auf die Deklaration von numfile als eine ganze Zahl riecht schlecht. Wenn der Test beispielsweise umgekehrt wird, um Dateien mit weniger als 100 Zeilen zu kopieren, wird versucht, Verzeichnisse zu kopieren. Wahrscheinlich ist es sicherer, einfach '&&' an das Ende der Zeile anzuhängen, die die Zuweisung von numfiles ausführt, oder '' für f in * zu schreiben; tue test -f "$ f" && test "$ (wc -l <$ f)" -ge 100 && cp "$ f"/pfad; done' –

+0

Was bedeutet [-f "$ f"]? – Jiangty

0

Probieren Sie etwas wie dies (POSIX sh):

#!/bin/sh 
SOURCE_FOLDER="/home/john/folder a" 
COPY_TO="/home/john/folder b" 

for dir in "$SOURCE_FOLDER" "$COPY_TO"; do 
    if [ ! -d "$dir" ]; then 
     echo "Directory ${dir} does not exist." >&2 
     exit 1 
    fi 
done 

if [ "x`ls -A "$SOURCE_FOLDER"`" = "x" ]; then 
    echo "Directory '${SOURCE_FOLDER}' is empty." >&2 
    exit 1 
fi 

for file in "$SOURCE_FOLDER"/*; do 
    LINES=`wc -l < "$file"` 
    echo "File ${file} has ${LINES} lines..." 

    if [ "$LINES" -ge 100 ]; then 
     echo "Copying ${file}..." 
     cp -a "$file" "${COPY_TO}/" 
    fi 
done 

Hier ist eine Bash-Version für Systeme mit Bash (sagte man Unix, Linux nicht, so dass Sie wahrscheinlich die Topversion wollen):

#!/bin/bash 
SOURCE_FOLDER="/home/john/folder a" 
COPY_TO="/home/john/folder b" 

for dir in "$SOURCE_FOLDER" "$COPY_TO"; do 
    if [[ ! -d "$dir" ]]; then 
     echo "Directory ${dir} does not exist." >&2 
     exit 1 
    fi 
done 

if [[ -z "$(ls -A "$SOURCE_FOLDER")" ]]; then 
    echo "Directory '${SOURCE_FOLDER}' is empty." >&2 
    exit 1 
fi 

for file in "$SOURCE_FOLDER"/*; do 
    LINES="$(wc -l < "$file"')" 
    echo "File ${file} has ${LINES} lines..." 

    if [[ "$LINES" -ge 100 ]]; then 
     echo "Copying ${file}..." 
     cp -a "$file" "${COPY_TO}/" 
    fi 
done 

ich es wie folgt getestet:

$ mkdir "folder a" 
$ mkdir "folder b" 
$ chmod +x script.sh 
$ cd folder\ a/ 
$ seq 1 1000 > file1.txt 
$ seq 1 1000 > file2.txt 
$ seq 1 100 > file4.txt 
$ seq 1 100 > file3.txt 
$ seq 1 99 > file4.txt 
$ seq 1 1 > file5.txt 
$ seq 1 20 > file6.txt 
$ cd .. 
$ ./script.sh 
File /.../dev/scratch/stack/folder a/file1.txt has 1000 lines... 
Copying /.../dev/scratch/stack/folder a/file1.txt... 
File /.../dev/scratch/stack/folder a/file2.txt has 1000 lines... 
Copying /.../dev/scratch/stack/folder a/file2.txt... 
File /.../dev/scratch/stack/folder a/file3.txt has 100 lines... 
Copying /.../dev/scratch/stack/folder a/file3.txt... 
File /.../dev/scratch/stack/folder a/file4.txt has 99 lines... 
File /.../dev/scratch/stack/folder a/file5.txt has 1 lines... 
File /.../dev/scratch/stack/folder a/file6.txt has 20 lines... 

ich Sie ermutigen, durch diese Leitung zu Schritt durch Zeile, herauszufinden, wie jeder Teil des Skripts funktioniert, um Ihnen bei ähnlichen Aufgaben in der Zukunft zu helfen.

werde ich hier ein paar Dinge erklären:

  • wc -l < "$file" uns nur die Zeilenzahl der Datei, ohne die Dateinamen gibt.
  • ist wahr, wenn in der Datei mindestens 100 Zeilen vorhanden sind.
  • echo "..." >&2 gibt eine Zeile als Standardfehler und nicht als Standardausgabe aus.
  • cp -a kopiert eine Datei unter Beibehaltung aller Attribute, z. B. Besitzer, Berechtigungen und Änderungszeit.
  • Stellen Sie sicher, alle Variablen zu zitieren, es sei denn, Sie haben einen guten Grund nicht, um Probleme mit Leerzeichen zu vermeiden.
+0

Sie benötigen keine Pipe, um die Zeilenanzahl zu erhalten. 'wc -l <" $ file "' würde auch tun. – user1934428

+0

Ausgezeichneter Punkt, korrigiert! Vielen Dank. – Will

1

Hier ist eine weitere:

# Assuming that we are in source folder ... 
cp $(wc -l *|grep -Eo '[0-9]{3,} (.*)'|head -n -1|cut -d ' ' -f 2) /dev/null "/home/john/folder b" 

Die head die von wc gedruckt Gesamt Linie entfernt, und die /dev/null kümmert sich um den Fall, dass Sie keine Dateien, die criterium entsprechen.

Natürlich wird diese Lösung - wie die anderen hier vorgestellt - Sie in Probleme bringen, wenn Ihr Quellverzeichnis so viele Dateien enthält, dass die maximale Befehlszeilenlänge überschritten wird.

+0

Ich mag die Idee, aber mit einem Regex-Match für den numerischen Vergleich scheint fragil. Wahrscheinlich einfacher 'wc -l * | awk '$ 1> 100 {print $ 2}' ... 'Es gibt immer noch Probleme mit Verzeichnissen. –

+0

In meiner Lösung werden Verzeichnisse implizit ignoriert. Ich sehe kein Problem mit der Regex-Übereinstimmung für die Zahlen, außer mit einem (leicht pathologischen Fall), wo mein Ansatz fehlschlagen würde: Stellen Sie sich eine Datei mit dem Namen '200 xx' vor (dh der Name beginnt mit einer dreistelligen Zahl und hat einen Platz eingebettet); Mit meiner Lösung würde die Datei kopiert werden, selbst wenn sie weniger als 100 Zeilen hat. Natürlich wer würde Dateien mit eingebetteten Leerzeichen im Namen erstellen .... ;-) – user1934428