I have isseued the next command in order to move some directories to the "build_tools" folder however the result was not the one I expected.

ls -l | grep 2014-03 | awk '{if ($8!=build_tools) print $8}' | xargs mkdir build_tools/{} && mv {}/ build_tools/{}/

It moved the folder "build_tools" to one of the folders yielded by awk (zlib) altogether with the rest of directories and then it got stuck with this message:

mkdir: no se puede crear el directorio «zlib»: El archivo ya existe

Can somebody shed some light on what is my mistake?


The output of ls -l gives me:

drwxr-xr-x  3 poissonbreaker poissonbreaker     4096 2011-05-02 09:58 antlr3.2
-rw-r--r--  1 poissonbreaker poissonbreaker   318588 2011-05-17 16:21 AppFramework-1.03.jar
-rw-r--r--  1 poissonbreaker poissonbreaker        0 2014-03-04 09:53 awk
drwxr-xr-x  4 poissonbreaker poissonbreaker     4096 2013-01-11 23:13 clutter-sharp
-rw-r--r--  1 poissonbreaker poissonbreaker      429 2014-01-14 09:49 Dependencias

I just want to get the files with the date field ($6) matching 2014-03, that is why I do a simple grep of it as (No file in the directory has as filename this pattern):

ls -l  | grep 2014-03 

Which yields:

-rw-r--r--  1 poissonbreaker poissonbreaker        0 2014-03-04 09:53 awk
-rw-r--r--  1 poissonbreaker poissonbreaker      429 2014-01-14 09:49 Dependencias

Then I get the filename field ($8) of every file through awk to finally be moved to build_tools folder (At this point I know what was my mistake -- the build_tools folder has also been created on this date :S). I will leave this question here though, in case some parts will be useful for anyone.

EDIT 2: I have changed the awk expression to:

awk '{if ($8!=build_tools) print $8}'

for it to make sense.

  • See my updated answer – slhck Mar 4 '14 at 12:09

I'm assuming that you have GNU find. If you want to move files or directories modified within a certain time span (e.g. March 2014) do this:

find . -maxdepth 1 \
-newermt 2014-02-28 -not -newermt 2014-04-01 \
-not -name 'build_tools' \
-exec mv {} build_tools \+


  • find in this directory, without subdirectories
  • files in the range between Feb. 28th and April 1st, where mt refers to modification time. You could also use ct to search for creation time.
  • that aren't named build_tools
  • move all of them to build_tools. The \+ means that all found file/directory names are replaced in {}, instead of one at a time. If you want one at a time, you need \; instead.

A couple of things:

  • Don't parse the output of ls. The format is dependent on the operating system, and picking columns with awk fails if the file / directory names contain whitespace.

  • You used & to concatenate commands, but & just puts a process into the background. If at all, you should have used &&, but all in all, it'd be rather complicated to achieve what you want.

  • I got it working my way but this seem to me the correct one. This is what I wanted, thanks! I cannot give you points yet, sorry. – poissonbreaker Mar 5 '14 at 11:26

The correct version for my solution needs xargs to handle multiple commands, which can be achived by wrapping the commands with:

sh -c (or bash -c) 'Command1; Command2; .. Comandn'

So the correct solution is:

ls -l awk ' $8!=build_tools && $6 ~ /2013-03*/ {print $8}' | xargs -I @ sh -c 'mkdir build_tools/@; mv @ build_tools/@'

Beware that this creates a new folder for each file to move.

The bottom line is that while other has take care of making our life easier with better and specialized tools, we can still learn a lot from old style piped queries. At least in my case :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.