Reputation: 661
I want to move all my files from a folder that have the numbers 1995, 1996, and 1997 to different folders.
Much of what I've found on this list has to do with moving any file that contains any pattern. I want the command to look in the directory, scan the .txt file's contents, and as soon as they find 1996, put it in the 1996 directory.
This means that if the command looks in the directory, scans the .txt file, and finds 1996 on the first line AND finds 1995 on the tenth line, it doesn't put the file in BOTH the 1996 and 1995 folders. I want it to only put the file in the 1996 folder.
grep -rl --null --include '*.txt' 1996 . | xargs -0 sh -c 'cp "$@" /folderpath' sh
This seems to put 1995 files into the 1996 folder just because it contains 1995 somewhere in the file.
Upvotes: 0
Views: 591
Reputation: 140980
I think something like this could work:
find . -name '*.txt' -print0 |
xargs -0 -n1 sh -c '
if a=$(head -n1 "$1" | grep -o "199[567]"); then
mv "$1" "./$a"
fi
' --
Alternatively the xargs
can be substituted with while IFS= read -r file; do
loop. That would look like:
find . -name '*.txt' -print0 |
while IFS= read -r file; do
if a=$(head -n1 "$file" | grep -o "199[567]"); then
mv "$file" "./$a"
fi
done
find
finds everything
.
- in the current directory-name '*.txt'
- with names ending with .txt
-print0
- and prints them as zero terminated list|
- pipe, passes the output of one command to anotherwhile
- executes a do ... done
body until the command returns non-zero exit statusIFS= read -r file
- a popular mnemonic to read zero separated list, see bashfaq How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
head -n1 "$file"
- extract first line from the filegrep
-o
- output the matched string only199[567]
- match 1995
or 1996
or 1997
grep
outputs a zero exit status if it matches successfully (important at if
)a=$(...)
- assign the output of the command to a
. The exit status of the process substitution $(...)
is the last command executed, grep
in this case.if command
- executes the then ... fi
body only if the command returns with a nonzero exit status. Ie. here only if grep matches the string successfully, it will return a zero exit status.
mv "$file" "./$a"
- the variable a
(bad naming...) contains the string that grep
matched so it will be 1995
or 1996
or `1997. So move the file to proper folder.Upvotes: 1