user3635159
user3635159

Reputation: 157

Copy selected files in bash

I'm trying to copy specific files between directories. So I listed all files with ls, added a line number with cat -n and then selected first 100 files I want to copy with head -100. After that I used xargs command but it does not work. Here is the code:

ls * | cat -n | head -100 | xargs -0 cp -t ~/foo/bar

The command reproduces a list of files on the screen and returns the warning File name too long.

I have tried also with -exec cp -t and its returns the message -bash: -exec: command not found.

Edit: My filenames contain years (e.g. 1989a, 1989b,1991a, 1992c) so I would like to select all files published before a certain year (e.g. 1993).

Upvotes: 1

Views: 742

Answers (3)

Ole Tange
Ole Tange

Reputation: 33725

Using GNU Parallel it will look like this:

ls | head -100 | parallel -X cp {} ~/foo/bar

Upvotes: 1

Tom Fenech
Tom Fenech

Reputation: 74685

This would result in 100 invocations of cp but you could just use a loop:

count=0; for i in *; do cp "$i" ~/foo/bar; ((++count == 100)) && break; done

Another way you could do this would be to use an array:

files=( * )
cp "${files[@]:0:100}" ~/foo/bar

The glob * expands to fill the array with the list of files in the current directory. The first 100 elements of the array are then copied.

Upvotes: 3

gniourf_gniourf
gniourf_gniourf

Reputation: 46853

Provided you don't have too many files (so as to not exceed the maximum number of arguments and maximum buffer length of arguments allowed arguments on your machine), you can use something like:

shopt -s nullglob
cp -t ~/foo/bar {1970..1993}*

to copy all files that have a name starting with a number that lies between 1970 to 1993 (inclusive). Note that this will also copy a file named 197444, if any, and also will try to copy directories that have a matching name (you'll get a warning that it's omitting it, unless you pass the -r flag too).

See:

Upvotes: 2

Related Questions