3

Basically, my hard drive is a mess and I have like 200+ sub-directories in a main directory. I want to essentially move all files in 200+ sub-directories that have the extension .txt etc to a new directory. For example, n00b.txt or n00b.txt.exe

So I try the following command in the main directory consisting of the 200+ subdirectories sudo mv **/*.txt ~/Desktop/tmpremo/

Instead I am getting this error: bash: /usr/bin/sudo: Argument list too long

Why am I getting it and how do I remove say .txt,.txt.exe? How do I fix it?

1

This would move all files with .txt and .txt.exe extensions present anywhere inside the current directory (even in subdirectories) to ~/Desktop/tmpremo.

$ sudo find . -type f \( -iname '*.txt' -o -iname '*.txt.exe' \) -exec mv {} ~/Desktop/tmpremo \;

If you want another extension too, just add -o -iname '*.extension' before the -exec.

PS: As @xenoid noted, please refrain from using sudo unless it is absolutely required for the task at hand.

| improve this answer | |
  • 1
    Thanks so much SIr! Worked like a charm so I accepted answer!! – n00bl1nux Dec 23 '19 at 13:15
  • The two -iname tests needs to be grouped as \( -iname ... -o -iname ... \). – Kusalananda Dec 23 '19 at 19:48
  • Fixed. Thanks! (But seriously, I don't see anyone creating directories or special files with .txt or .txt.exe in their names). – Mukesh Sai Kumar Dec 24 '19 at 6:38
1

(newbie here so I can't comment @BarBar1234's answer)

I believe there's no need to echo the output of 'find', as the command itself already echoes the founded filenames.

So instead you could just use:

sudo find . -type f -iname '*.txt'

But, for the sake of knowledge, the outputs you were getting (find: ‘echo ./rdggt_169/frretcdd_td.txt ’: No such file or directory) happens because in the command

sudo find . -type f -iname '*.txt' -exec 'echo {}'  \;

the part that says -exec 'echo {}' is giving a single-quoted argument to -exec, therefore, it treats the whole expanded string as a command.

To be clear, the string 'echo foo/bar.txt' is not the command echo with a 'foo/bar.txt' argument, that's why nothing was found in your system, because no command exists in your system with the name echo foo/bar.txt.

That's why BarBar1234 just edited the answer, removing the single quotes. Now echo is treated as what is supposed to be treated in this case, a command, not a string.

| improve this answer | |
1

You are getting the error because **/*.txt is expanded with all the matching files (with full paths) as a very long command line, and there is a limit to the length to the arguments.

A problem with using find ... -exec mv is that you run mv once for each file.

There is a command that will attempt to run commands with the maximum allowed number of arguments: xargs, so you just need to pipe the output of find to xargs and tell xargs to run mv (arguments are by default appended at the end):

find . -type f -name '*.txt' -print0 | xargs -0 mv -t ~/Desktop/tmpremo

PS: I'm surprised that you have to use sudo to move files inside your own user directories.

| improve this answer | |
1

Since you're already using **, why not do a simple loop?

for name in ./**/*.txt ./**/*.txt.exe; do
    mv "$name" "$HOME/Desktop/tmpremo"
done

The Argument list too long error is due to the shell trying to execute a command with too many/long arguments. This is a limitation in one of the exec() family of C library functions, which has a restriction on the sum of the length of the arguments and the combined size of all environment variables (on Linux, it's slightly more complicated with each argument having a maximum allowed length too I believe, but that's details).


I can see from your error message that you are using bash, but if you were a zsh user and had GNU mv, you could instead do

autoload -U zargs
zargs -- ./**/*.txt(.) ./**/*.txt.exe(.) -- mv -t "$HOME/Desktop/tmpremo"

The zargs utility is a bit like xargs, but implemented as a loadable zsh shell function. See zargs --help ofter loading it, and the zshcontrib(1) manual.

| improve this answer | |
0

try this from the top level directory where the subdirectories are located:

sudo find . -type f -iname '*.txt' -exec echo {}  \;

and if the list of files found shows a list of text files in question, do:

sudo find . -path ~/Desktop/tmpremo -prune -o -type f -iname '*.txt' -exec mv {} ~/Desktop/tmpremo/ \;
| improve this answer | |
  • thanks for replying sir. i tried the first command and for some strange reason or another I am getting a load of this find: ‘echo ./rdggt_169/frretcdd_td.txt ’: No such file or directory I can see it in directories though – n00bl1nux Dec 23 '19 at 2:02
  • I corrected the commands, the ' around exec commands were not necessary. – BarBar1234 Dec 23 '19 at 2:43

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.