Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash Shell awk/xargs magic

Tags:

bash

awk

xargs

I'm trying to learn a little awk foo. I have a CSV where each line is of the format partial_file_name,file_path. My goal is to find the files (based on partial name) and move them to their respective new paths. I wanted to combine the forces of find,awk and mv to achieve this but I'm stuck implementing. I wanted to use awk to separate the terms from the csv file so that I could do something like
find . -name '*$1*' -print | xargs mv {} $2{}
where $1 and $2 are the split terms from the csv file. Anyone have any ideas?
-peace

like image 830
adbo Avatar asked Nov 11 '11 04:11

adbo


People also ask

What is awk '{ print $1 }'?

If you notice awk 'print $1' prints first word of each line. If you use $3, it will print 3rd word of each line.

What is xargs command in bash?

The xargs command builds and executes commands provided through the standard input. It takes the input and converts it into a command argument for another command. This feature is particularly useful in file management, where xargs is used in combination with rm , cp , mkdir , and other similar commands.

What is awk F?

awk -F, ' program ' input-files. sets FS to the ' , ' character. Notice that the option uses an uppercase ' F ' instead of a lowercase ' f '. The latter option ( -f ) specifies a file containing an awk program.


2 Answers

I think you've got things mixed up here. {} can only be used in find, and only once. I.e you cannot do something like find -name '*.jpg' -exec mv {} {}.png.

Do this:

$ cat korv
foo.txt,/hello/
bar.jpg,/mullo/
$ awk -F, '{print $1 " " $2}' korv
foo.txt /hello/
bar.jpg /mullo/

-F sets the delimiter, so the above will split using ",". Next, add * to the filenames:

$ awk -F, '{print "*"$1"*" " " $2}' korv
*foo.txt* /hello/
*bar.jpg* /mullo/
**

This shows I have an empty line. We don't want this match, so we add a rule:

$ awk -F, '/[a-z]/{print "*"$1"*" " " $2}' korv
*foo.txt* /hello/
*bar.jpg* /mullo/

Looks good, so encapsulate all this to mv using a subshell:

$ mv $(awk -F, '/[a-z]/{print "*"$1"*" " " $2}' korv)
$

Done.

like image 76
bos Avatar answered Sep 23 '22 01:09

bos


You don't really need awk for this. There isn't really anything here which awk does better than the shell.

#!/bin/sh
IFS=,
while read file target; do
  find . -name "$file" -print0 | xargs -ir0 mv {} "$target"
done <path_to_csv_file

If you have special characters in the file names, you may need to tweak the read.

like image 44
tripleee Avatar answered Sep 26 '22 01:09

tripleee