I need some help with some Linux / Unix commands, please.

I submitted this accidentally… please see next post for content.

null

Problem:

I have uploaded tens of thousands of files accidentally to directory where I want them all to be singly:

file 1
file 2
tile 3

etc.

Instead, I uploaded them in subfolders, almost 600 of them, so that the directory structure is:

directory1/directory2/directory3/DIRECTORY_I_WANT_FILES_TO_BE_IN/1000 to 1100/file1.jpg
directory1/directory2/directory3/DIRECTORY_I_WANT_FILES_TO_BE_IN/1000 to 1100/file2.jpg
directory1/directory2/directory3/DIRECTORY_I_WANT_FILES_TO_BE_IN/1000 to 1100/file3.jpg
directory1/directory2/directory3/DIRECTORY_I_WANT_FILES_TO_BE_IN/1000 to 1100/file4.jpg
directory1/directory2/directory3/DIRECTORY_I_WANT_FILES_TO_BE_IN/1000 to 1100/file5.jpg

etc for another 95 files, then the next one

directory1/directory2/directory3/DIRECTORY_I_WANT_FILES_TO_BE_IN/1101 to 1200/file100.jpg
directory1/directory2/directory3/DIRECTORY_I_WANT_FILES_TO_BE_IN/1101 to 1200/file101.jpg
directory1/directory2/directory3/DIRECTORY_I_WANT_FILES_TO_BE_IN/1101 to 1200/file102.jpg
directory1/directory2/directory3/DIRECTORY_I_WANT_FILES_TO_BE_IN/1101 to 1200/file103.jpg
directory1/directory2/directory3/DIRECTORY_I_WANT_FILES_TO_BE_IN/1101 to 1200/file104.jpg
directory1/directory2/directory3/DIRECTORY_I_WANT_FILES_TO_BE_IN/1101 to 1200/file105.jpg
So a friend told me that I could use the mv command to move all the jpgs out of the individual directory/folders and into DIRECTORY_I_WANT_FILES_TO_BE_IN.

But I’m having a bitch of a time, it’s not working.

I looked at the help file for the mv command, and the first thing that jumped out at me was the
-T
and
-t

which make a big difference, since I could end up renaming things instead of moving them.

So basically I need to know how to write the command that does this:

(assuming that I am actually IN the DIRECTORY_I_WANT_FILES_TO_BE_IN directory…)

Find all the .jpg files that are contained in the directories that are in this diectory.
Then move them directly into this directory itself, discarding the subdirectories/folders they are now in.

And the numbered directories are named as I showed them…with spaces between the numbers and the word “to”, which my friend tells me means I must refer to them with question marks or \backslashes in the spaces.

help…

Ok, I just did an experiment on this, and to move the files out of the subdirectories I came up with (assuming you’re in DIRECTORY_I_WANT_FILES_TO_BE_IN)


for x in */*.jpg; do mv "$x" .; done

And then to remove the (now empty, I think) directories,


find * -type d -print0 | xargs -0 rmdir

I should add: if you have other sub-directories other than “1000 to 1100”, “1101 to 1200”, etc., these codes will need to be modified a bit.

A little more experimenting, and I’ve got


find *\ to\ * -name *.jpg -print0 | xargs -0 mv -t.

to move the files out of your subdirectories, and


find *\ to\ * -type d -print0 | xargs -0 rmdir

to remove the empty directories. This should leave any other subdirectories untouched, if there are any others.

I would check to make sure the directories are actually empty before deleting them. find is the best tool but I’ve always hated it, so I did it the ugly way.


ls -d */ | while read line; do [[ -z $(ls -A "$line") ]] && rm -rf "$line"; done

test with echo:

mkdir ‘1101 to 1200’ ‘1000 to 1100’

touch ‘1000 to 1100’/foo.txt

ls 1*

1000 to 1100:
foo.txt

1101 to 1200:

ls -d */ | while read line; do [[ -z $(ls -A “$line”) ]] && echo “$line is empty”; done

1101 to 1200/ is empty

rmdir only deletes empty directories by default. This shouldn’t be a problem.

It is amazing how nothing ever seems to work and how many different ways unix/linux seems to ahve to do things.

I really have only the vaguest idea about what I’m doing here, in case that wasn’t obvious.

I tried:

find *\ to\ * -name *.jpg -print0 | xargs -0 mv -t.

and this was the error:

my actual pwd:

/var/www/vhosts/domain.com/httpdocs/members/pictorials/photos
directory listing shows a bunch of individual photos (since I’ve been doing it by hand via drag and drop and I’ve worked through about 10,000 of the 60,000 files…) AND the following directories (partial)

30201 to 30300
30301 to 30400
30401 to 30500
30501 to 30600
30601 to 30700
30701 to 30800
30801 to 30900
30901 to 31000
31001 to 31100
31101 to 31200
31201 to 31300
31301 to 31400
31401 to 31500
31501 to 31600
31601 to 31700
31701 to 31800
31801 to 31900
31901 to 32000
32001 to 32100
32101 to 32200
32201 to 32300
32301 to 32400
32401 to 32500
32501 to 32600
32601 to 32700
32701 to 32800
32801 to 32900
32901 to 33000
33001 to 33100
33101 to 33200
33201 to 33300
33301 to 33400
33401 to 33500
33501 to 33600
33601 to 33700
33701 to 33800
33801 to 33900
33901 to 34000
etc.
which each contain a hundred jpegs

so, now that you know exactly what it is, can you tell me exactly what the command is to pull all the jpgs out of hte folders and into the folder I’m in, which is /photos/?

Let’s try a slightly different syntax for the find command. How about:


find . -path "./*to*/*.jpg"

This should return a complete listing of every .jpg file in your folders “30201 to 30300”, “30301 to 30400”, etc (and none of the photos in directory you’re currently in). You can check that none of the files in the /photos/ directory are seen by appending the command


find . -path "./*to*/*.jpg" | grep -v " to "

This command should return nothing.

If everything looks ok so far, then append the xargs command, so it looks like


find . -path "./*to*/*.jpg" -print0 | xargs -0 mv -t .

Sheesh, 10 years using nothing but Linux and I never realized that.

Since it sounds like it might be a looonnnng list, you might want to pipe the output to less to buffer the list for display on the screen. That is, rather than just having the list scroll off the screen.

Oh, the modified command would be (the vertical line is a “pipe”):


find . -path "./*to*/*.jpg" | less

Call me lazy, but why not just:

mv /.jpg ./ && rmdir *

?

So nothing that you guys or my other friend told me to do worked. nothing.

Here’s what did.

I ran the find command accidentally all by itself. This was interesting, because what it returned was a listing of every file that was deeper than where I was, with the file path - I think I ran it from within /photos/, but if not it was from one level up.

it looked like this:

./photos/30401?to?30500/60ccba-9919.jpg
./photos/30401?to?30500/60ccba-9920.jpg
./photos/30401?to?30500/60ccba-9921.jpg

Which I found very interesting. Especially the dot.

So, rather than continue to wrestle, I did what made sense to me.

I copied the list of 50,000 photos and their exact paths to a BBedit file.
I search/replaced ./ with mv ./, then replaced .jpg with .jpg photos, which of course gave me:

mv ./photos/30401?to?30500/60ccba-9919.jpg photos
mv ./photos/30401?to?30500/60ccba-9920.jpg photos
mv ./photos/30401?to?30500/60ccba-9921.jpg photos
mv ./photos/30401?to?30500/60ccba-9922.jpg photos
mv ./photos/30401?to?30500/60ccba-9923.jpg photos
mv ./photos/30401?to?30500/60ccba-9924.jpg photos
mv ./photos/30401?to?30500/60ccba-9925.jpg photos
mv ./photos/30401?to?30500/60ccba-9926.jpg photos
mv ./photos/30401?to?30500/60ccba-9927.jpg photos
mv ./photos/30401?to?30500/60ccba-9928.jpg photos
mv ./photos/30401?to?30500/60ccba-9929.jpg photos
I pasted a couple of lines at the bash prompt.
It worked.
So I pasted 5000 lines of it.
THAT worked. (And created a very psychedelic visual!)

So I pasted the other 45,000 lines and went and had dinner with a neighbor.

It worked.

The long way around, I suppose, but IT WORKED.

That’s nothing, this is the first time I’ve ever even heard of a rmdir command in Linux. I’ve only known about/used rm -R.

Really? Mind if I ask what kind of Linux you’re using?

Next time you have a file with 45,000 commands to run, you can just do this at the bash prompt.


. filename

Just a dot and the filename. Bash will “source” the file, meaning it will read the file and run all the commands in it.

CentOs is what I think its called

…ummm…sure…whatever that means…(I had 50,000 filenames, only one command)

With the greatest respect and deference, I’ve been having people here and elsewhere say “You JUST… blah blah blah” for days, like it’s all supposed to be perfectly clear. IT IS NOT. I’m new at this. If you want to be helpful and nice, I’m very grateful…but it requires holding my hand and walking me through ALL The steps. “you just [insert incomplete and vague reference here]” is completely useless to me.

Except that it gives me just enough information to do what I ended up doing, I guess. (re: find)

I’m a very intelligent woman and I’m pretty comfortable with computers, (I actually learned how to use a computer via command line, seeing as my introduction to computers was CP/M, which predates ms-dos- but that was a quarter century ago. Once I met Macintosh, I left all that crazy command line shit behind me, and happily so.) but command line is a whole other mindset, one I don’t naturally possess. So when I do ANYTHING with it, I need to have it all sort of translated into English.

I do appreciate the time and effort, I truly do.

It means you save the big ugly command line into a file and then ‘source’ it the next time you need it. Which isn’t how I’d do it, BTW: I’d put it into a file, but I’d then give the file executable permissions by typing ‘chmod +x filename’ and make sure the file was in ~/bin or some other directory listed in my $PATH environment variable.

If anything in the above was hazy or unclear to you, you need to read something like this bash scripting tutorial. CentOS (which is Red Hat Enterprise Linux in every essential respect; in case you see ‘RHEL’ mentioned that’s what it means) ships with bash as its default shell and it’s the one you’re using unless you know you aren’t.

You might follow it up with the Advanced Bash Scripting Guide, which will take you to the point where you should be able to do most of this stuff without problems.

This is understandable. I think the intention is to make it clear that none of this is magical or beyond you; it’s just badly phrased.

Ah, the land of PIP and BDOS! :slight_smile: You can travel back to those thrilling days of yesteryear with simh and an appropriate software kit.

The Linux Documentation Project has a set of guides on many topics which are frequently useful. Bash Guide for Beginners might be of particular interest here.