Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I have directory /logos which contains approximately 10000 png images. Can you please suggest some script to make two new folders /logos-1 and /logos-2 each one with half of the images from initial folder?
Thank you in advance <3
One approach could be to iterate over the files in the folder, keep and counter and move they files the other directory on each iteration:
counter=0
mkdir -p logos-0
mkdir -p logos-1
for file in logos/*
do
[ -e "$file" ] || continue
echo mv "$file" "logos-$((counter++%2))/"
done
Remove the echo if the mv commands looks appropriate.
You can use rename, a.k.a. Perl rename and prename for that. I assume you don't really want the leading slashes and you aren't really working in the root directory - put them back if you are.
rename --dry-run -p -N 01 '$_ = join "", "logos-", $N++%2+1, "/$_"' *.png
Sample Output
'1.png' would be renamed to 'logos-2/1.png'
'10.png' would be renamed to 'logos-1/10.png'
'2.png' would be renamed to 'logos-2/2.png'
'3.png' would be renamed to 'logos-1/3.png'
'4.png' would be renamed to 'logos-2/4.png'
'5.png' would be renamed to 'logos-1/5.png'
'6.png' would be renamed to 'logos-2/6.png'
'7.png' would be renamed to 'logos-1/7.png'
'8.png' would be renamed to 'logos-2/8.png'
'9.png' would be renamed to 'logos-1/9.png'
You can remove the --dry-run if the output looks good. The -p means it will create any necessary directories/paths for you. If you aren't familiar with Perl that means:
"Set N=1. For each PNG file, make the new name (which we must store in special variable $_) equal to the result of joining the word logos- with a number alternating between 1 and 2, with a slash followed by whatever it was before ($_)."
You may find this alternative way of writing it easier:
rename --dry-run -N 01 '$_ = sprintf("logos-%d/$_", $N%2+1)' *.png
Using this tool confers several benefits:
you can do dry runs
you can calculate any replacement you like
you don't need to create directories
it will not clobber files if multiple inputs rename to the same output
On macOS, use homebrew and install with:
brew install rename
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
My code is meant to find a /jar folder , loop through the .jar files and create .xml and .trigger files with the same file name. Additionally, it creates an ~ID~ filename ~ID~ field within the XML file.
I am getting the error
mkdir: cannot create directory '': No such file or directory
I have the /tmp folder set up, including an /xml /jar and /trigger folder, so those not being there isn't the issue.
#!/bin/bash
jar_dir= /c/Users/hi/Desktop/Work/tmp/jar
xml_dir= /c/Users/hi/Desktop/Work/tmp/xml
trigger_dir= /c/Users/hi/Desktop/Work/tmp/trigger
# the following creates output directories if they don't exist
mkdir -p "${xml_dir}"
mkdir -p "${trigger_dir}"
# we start the for loop through all the files named `*.jar` located in the $jar_dir directory
for f in $(find ${jar_dir} -name "*.jar")
do
file_id=$(basename -s .jar ${f}) # extract the first part of the file name, excluding .jar
echo "<ID>${file_id}</ID>" > ${xml_dir}/${file_id}.xml
touch ${trigger_dir}/${file_id}.trigger # this one just creates an empty file at ${trigger_dir}/${file_id}.trigger
done
This command:
jar_dir= /c/Users/hi/Desktop/Work/tmp/jar
is exactly equivalent to
jar_dir="" /c/Users/hi/Desktop/Work/tmp/jar
and tells the shell to run the command /c/Users/hi/Desktop/Work/tmp/jar with the environment variable jar_dir set to the empty string (only for the duration of that command). If /c/.../jar is a directory, that should give you an error, too.
To assign the /c/.../jar string to the variable instead, lose the space.
The error message you get comes from mkdir trying to create a directory with an empty name. (It's a bit confusing though.)
For problems with shell scripts, it often helps to paste the script to https://www.shellcheck.net/, which recognizes most of the usual mistakes and can tell what to do.
See these posts on SO and unix.SE for discussion:
Command not found error in Bash variable assignment
Is it shell portable to run a command on the same line after variable assignment?
Spaces in variable assignments in shell scripts
xml_dir= /c/Users/hi/Desktop/Work/tmp/xml
Can't have a space after the equal. So
xml_dir=/c/Users/hi/Desktop/Work/tmp/xml
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I ran this command that a user on reddit wrote for me:
dest=final_dir
files=$(find dir1 dir2 dir3 -type f)
for file_path in $files; do
IFS='/' read -r -a tokens <<< "$file_path"
dest_fname="${tokens[1]}.${tokens[0]}"
ln -s "$PWD/$file_path" "$PWD/$dest/$dest_fname"
done
It is supposed to take all files in all subfolders and create a symlink to another directory with the name of the link being filename+filefolder.
It does however only give me the error: failed to create symbolic link - no such file or directory
here is a screenshot of the console:
https://imgur.com/36F4sdX
any ideas what could be the problem?
Edit:
Ok, the problem seems to be that it when the path includes a space, it thinks the name stops at this space and thus doesnt find the file. Any idea how to fix this?
Here a description of what the script is supposed to do.
my current filesystem looks like this:
dir1: file1, file2
dir2: file1, file2
if i now run the above command i get:
dir3: file1, file2
and the other 2 files are skipped as they have the same name.
also given this scenario:
dir1: file1, file3
dir2: file2, file4
in this case the files would be mixed to:
dir3: file1, file2, file3, file4
what i want though is:
dir3: file1, file3, file2, file4
In my opinion the easiest way to achieve this would be to make the source folder part of the symlinks name, like this:
dir3: dir1-file1, dir1-file3, dir2-file3, dir2-file4
I hope this explains it well enough.
The problem right now seems to be that when file- or foldername contain any special characters like "-" or "_" it stops reading the name at that point.
This results in:
dir1-2: file3-4 creating a symlink to dir1.file3 which doesnt exist
ln -s does not care about whether the source path exists, so the problem must be with the target path. The command creates a symbolic link, so if it is complaining that a file or directory does not exist then the issue must be with the path to the target link, not the link's name.
In your case, the target path is "$PWD/$dest/$dest_fname".
From its construction, it does not appear that $dest_fname can contain / characters, so it is a simple file name without any path components.
$PWD represents (the shell's idea of) the present working directory. Unless you are playing games with that variable or the working directory has been deleted out from under you, $PWD will expand to the name of an existing directory.
That leaves $dest as the probable locus of the issue. The script does nothing to ensure that the directory it designates exists, so the most plausible explanation is that it does not. Consider adding
mkdir -p "$PWD/$dest"
to your script, immediately prior to the for loop, if you want it to create the destination directory at need.
This question already has answers here:
Rename multiple files based on pattern in Unix
(24 answers)
Closed 2 years ago.
I have a folder containing a sequence of files whose names bear the form filename-white.png. e.g.
images
arrow-down-white.png
arrow-down-right-white.png
...
bullets-white.png
...
...
video-white.png
I want to strip out the -white bit so the names are simply filename.png. I have played around, dry run with -n, with the Linux rename command. However, my knowledge of regexes is rather limited so I have been unable to find the right way to do this.
If you are in the directory above images, the command is
rename "s/-white.png/.png/" images/*
If your current directory is images, then run rename "s/-white.png/.png/" ./* instead. To do a dry run, just attach a -n like you said:
rename -n "s/-white.png/.png/" images/*
or
rename -n "s/-white.png/.png/" ./*
This question already has answers here:
How to rename with prefix/suffix?
(10 answers)
Closed 7 years ago.
there are 30 files named like this:
sample_kmer_41_2.lib1.bowtie.file1.27.faabyss_sample
I need the output to be:
abyss_sample_kmer_41_2.lib1.bowtie.file1.27.fa
I don't know how to do this, I've already screwed the names up a lot. thanks for any help.
Use the rename utility:
rename 's/(.*)\.fa(.*)_sample$/$2_$1/' *
rename is part of the perl package and is installed by default on debian-like systems. There is a different and incompatible rename utility that is provided as part of the util-linux packages.
If you have the Perl-based prename (possibly named rename) command, then:
prename 's/(.*)abyss_sample$/abyss_$1/' sample_kmer_*
The exact regex to use depends on how the names have been damaged. This should work for the example name given; it may need tweaking to work with other names.
You could use a for loop. Since I'm always nervous about this stuff I'd recommend doing an echo first to make sure everything looks groovy...
#!/bin/bash
for FILE in sample_kmer_41_2*abyss_sample ; do
NEWNAME=`echo $FILE | sed -e 's/abyss_sample//'`
echo mv $FILE $NEWNAME
done
Provided that doesn't need tweaking, you can remove the echo or make modifications as necessary.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Consider two directories:
/home/user/music/flac
/media/MUSIC/flac
I would like the second directory (destination; a USB drive) to contain the same files and structure as the first directory (master). There are 3600+ files (59G in total). Every file is scanned using unison, which is painfully slow. I would rather it compare based on file name, size, and modification time.
I think rsync might be better but the examples from the man pages are rather cryptic, and Google searches did not reveal any simple, insightful examples. I would rather not accidentally erase files in the master. ;-)
The master list will change over time: directories reorganized, new files added, and existing files updated (e.g., re-tagging). Usually the changes are minor; taking hours to complete a synchronization strikes me as sub-optimal.
What is the exact command to sync the destination directory with the master?
The command should copy new files, reorganize moved files (or delete then copy), and copy changed files (based on date). The destination files should have their timestamp set to the master's timestamp.
You can use rsync this way:
rsync --delete -r -u /home/user/music/flac/* /media/MUSIC/flac
It will delete files in /media/MUSIC/flac (never on master), and update based on file date.
There are more options, but I think this way is sufficient for you. :-)
(I just did simple tests! Please test better!)
You can use plain old cp to copy new & changed files (as long as your filesystems have working timestamps):
cp -dpRuv /home/user/music/flac /media/MUSIC/
To delete files from the destination that don't exist at the source, you'll need to use find. Create a script /home/user/bin/remover.sh like so:
#!/bin/bash
CANONNAME="$PWD/$(basename $1)"
RELPATH=$(echo "$CANONNAME" | sed -e "s#/media/MUSIC/flac/##")
SOURCENAME="/home/user/music/flac/$RELPATH"
if [ ! -f "$SOURCENAME" ]; then
echo "Removing $CANONNAME"
rm "$CANONNAME"
fi
Make it executable, then run it from find:
find /media/MUSIC/flac -type f -execdir /home/user/bin/remover.sh "{}" \;
The only thing this won't do is remove directories from the destination that have been removed in the source - if you want that too you'll have to make a third pass, with a similar find/script combination.