New answers tagged

1

I know this is an old question but i have been searching all night for a similar solution. I found a few helpful tips but they did not do exactly what i needed, so I had to mix and match a few to get the correct outcome I was looking for to simply remove special characters and replace them with a (.) dot for f in *.txt; do mv "$f" `echo $f | sed ...


0

Simple example to change the prefix and the extension of all images in the current folder. prefix=EG_ extension=.jpg for i in $(ls); do mv $i "$prefix${i%.JPG}$extension"; done If you want to check how it would effect your data before changing it replace the mv by echo output for IMG_7993.JPG is EG_IMG_7993.jpg


0

If you have the Perl-based rename utility (called prename on some distributions) you can use a Regular Expression to rename all the files in one go. Your requirement asks for the removal of sf{number}-{number} but all the examples start with capitals, some of them contain only one {number}, {number}-{number}-{number}, or even ...


0

You say you need everything deleted until {text}, but your example doesn't show that. Rather than showing exact code, let me just suggest a plan. 1) Write a script that does what you want for one filename. Something like this might do: #! /bin/sh test -d ~/OK/${PWD} || mkdir -p ~/OK/${PWD} ln "$1" "~/OK/${PWD}/$1" echo "$1" | awk -F ' - ' '{print $NF}' ...


0

While there are good answers already here, I find this more intuitive, within bash: find aaa -type f -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); mv "{}" "$new"' \; Where aaa is your existing directory. The files it contains will be moved to the current directory (leaving only empty directories in aaa). The two calls to tr handle both ...


2

Your regular expression doesn't match the pattern in your filename. To match at least one digit, you need to use [0-9]+ (you can also use \d to match digits); your pattern will only match 1 digit. Your example filename doesn't have spaces around -, but you have them in the pattern. And you're not doing anything to remove the ] at the end. Try: rename ...


0

The easiest tool here would be zsh (like bash, only better), with its fancy globbing and the zmv function. Run this from the toplevel directory where you want to rename files. autoload -U zmv zmv '(**/)[Ss][Ff][0-9]##-[0-9]##[- ]#(*)' '$1$2' Explanation: **/ is any string of leading directories. Then there's a pattern of sf (case-insensitive) followed by ...


0

Here is the code (replace directory by the main directory, or where you have the subdirs): cd directory find -type f | while IFS= read - file; do name=$(echo "$file" | rev | cut -d'/' -f1 | rev | cut -d'-' -f3- | cut -d' ' -f2-) path=$(dirname "$file") newname="${path}/${name}" echo mv "$file" "$newname" done Where directory is the ...


0

I hope it won't be a crime, to answer my own question. I've found partial solution at AskUbuntu - works for me, at least in the first case. touch -d "$(date -R -r filename) - 2 hours" filename And for modification of all files in subfolder, type: find DIRECTORY -print | while read filename; do # do whatever you want with the file touch -d "$(date ...


1

Using bash's built-in substring expansion: for f in 2015* ; do mv "$f" "${f::4}-${f:4:2}-${f:6}" done


1

While rename is a very powerful tool, I normally prefer the simplicity of the mmv (multiple move) utility: mmv '????????_*' '#1#2#3#4-#5#6-#7#8_#9' The ? in the search pattern stands for a single character, the * for an arbitrarily long sequence of characters. In the replacement pattern, every #<number> stands for a corresponding ? or * in the ...


1

Using the perl rename command (which is completely different to the rename command from util-linux): rename -v 's/^(\d{4})(\d{2})(\d{2})/$1-$2-$3/' 2015* (use -n rather than -v for a dry-run to test the command first). This perl version of rename may be called prename or file-rename on your system. It is far more capable and useful than the util-linux ...


2

With sed: LC_ALL=C sed -e 's/\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1_\2_\3/' <file


0

quick and dirty not full solution #!/usr/bin/env bash str=$1 yyyy=$(echo "$str" | awk -F '_' '{print $1}' | awk '{print substr($0, 1, 4)}') mm=$(echo "$str" | awk -F '_' '{print $1}' | awk '{print substr($0, 5, 2)}') dd=$(echo "$str" | awk -F '_' '{print $1}' | awk '{print substr($0, 7, 2)}') new_str=$yyyy-$mm-$dd'_'`echo $str | awk -F'_' '{print $2}'` echo ...


0

To rename all such files (with 8-digit dates at the beginning) in the current directory: #!/usr/bin/perl my @files = glob "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_*"; foreach my $file ( @files ) { my ( $y, $m, $d, $rest ) = $file =~ m/^(\d\d\d\d)(\d\d)(\d\d)(_.*)$/ or next; rename $file, "$y-$m-$d$rest"; }


0

On my distribution I have the perl-rename command, which can use a perl-style regex to bulk-rename files. The rename command only accepts a pair of fixed strings for the rename.


1

Here's a fairly simple and straight-forward shell script that uses jsonpipe to do what you want. It doesn't use any fancy sh/bash features, and does only the bare minimum sanity checking of filenames. NOTE: jq is far more capable than jsonpipe, but jsonpipe is simpler and easier to use when you don't particularly care (or want to know) about the structure ...


0

rename doesn't support regex on my distro. I have to use perl-rename. I am assuming that you're running the above command from a directory above the one in question.


0

Try this: #!/bin/bash if [ -f "$1" ]; then cp -v "$1" _"$1" rename -v 's/_(.+?)\./$1_copy\./' _"$1" fi The script checks if the input file that receives as input exists. In that case, it makes a temporary copy of the file and then renames such copy replacing the first dot in its name with the string _copy. I hope it is what you needed.


0

If you have ksh93 (for the arrays) and perl (for the timestamp/stat), then this will work: files=(*.xls) # exit early if there are no matching files [ "$files" = "*.xls" ] && exit 0 for index in ${!files[@]} do t[$index]=$(perl -e '$x=(stat(shift))[9]; print "$x"' "${files[index]}") done for i in ${!t[@]} do printf "%d %d\n" ${t[i]} $i done | ...


1

If you don't want to make any assumption on what character filenames may contain, you could do: ls -dt ./*.xls | awk -v q="'" -v n=10 ' function process() { if (NR > 1) { gsub(q, q "\\" q q, file) print "mv " q file q, q file "-bkp" q if (!--n) exit } } /\// { process() file = $0 next } {file = file "\n" ...


2

You should use -10 and not -1 as argument to head, and you also need quotes around -bkp, so ls -lt *.xls | head -10 | awk '{print "mv " $9 " "$9"-bkp"}' | sh should work. And you would probably have realised if you had tried removing | sh, so the command just ends with awk printing the commands.


-2

ls has a "sort"-parameter that can take a value of "time". #!/bin/bash IFS=$'\n' for file in $(ls *.xls --sort=time|head -n 10); do mv $file $file-bkp done unset IFS The IFS-shenanigans are because the for-loop becomes ill-mannered if you have spaces in your filenames. I believe there are more orthodox solutions to that issue, but my solution works. ...


3

You can use the rename command (see edit 1). Solution 1 For a reasonable number of files/directory, by setting bash 4 option globstar (not works on recursive name, see edit 3): shopt -s globstar rename -n 's/etckeeper/userkeeper/g' ** Solution 2 For a big number of files/directories using rename and find in two steps to prevent failed rename on files ...


0

Another solution is to use a small script and do a for loop on the find results and a mv with a bash string replacement on the files found : IFS=$'\n' for files in $(find . -name "*etckeeper*"); do mv "$files ${files/etckeeper/usrkeeper}" done If you don't use it in the script, then better save the original IFS and restore it at the end of the loop. ...


0

Your original question is actually pretty easy to answer: xargs (at least on OS X) has an -I option, too, which does not require that the replacement string be a unique argument. So, the invocation simply becomes: % find . -path '*etckeeper*' -print0 | xargs -0 -n 1 -I % bash -c 'echo mv % $(echo % | sed "s/etckeeper/usrkeeper/g" )' Easy peasy. Now, let's ...


2

You want to do the rename backwards: counter=$((final_number + 1)) for index in {final_number..0}; do mv "icon_${index}.icns" "icon_${counter}.icns"; let counter--; done


0

Initialize your counter with the value 1 instead of 0, and increase it after a move is done. Then you won't need to run a secondary bash script just for renaming the files, you would address it in the original script. Also, why when you increase your counter you add " || true" ? it has no meaning. Try this code counter=1 for img in SOURCE_FOLDER/*.png; do ...


1

Your problems will be solved by the following code: #!/bin/sh i=0 for img in `ls SOURCE_FOLDER_W_GOOD_NAMES/*.png`; do mv $img DESTINATION_FOLDER_W_INCREMENT_NAMES/icon_$i.icns i=$((i+1)); done


0

This works for me in Bash 4.2.46, it moves all files and folders including hidden files and folders to another directory mv /sourcedir/{,.[^.]}* /destdir/ Notice that .[^.]* means all hidden files except . and ..


1

With the prename utility found on Debian and derivatives or available on other systems by installing the Perl package Unicode::Tussle: prename 's ([^/]*\z) (sprintf("C0_%02d_%s", ++$n, $&))e' england.txt canada.txt france.txt Explanation: for each argument, rename the base name (the longest suffix not containing a slash) to C0_ followed by the counter ...


3

This does what you ask: n=1; for f in *.txt; do mv "$f" "CO_$((n++))_$f"; done How it works n=1 This initializes the variable n to 1. for f in *.txt; do This starts a loop over all files in the current directory whose names end with .txt. mv "$f" "CO_$((n++))_$f" This renames the files to have the CO_ prefix with n as the counter. The ++ symbol ...


2

AFAIK, in this context the {} aren't really "shell curly braces" (in the sense of brace expansion for example), they're just textual placeholders for arguments. As such you could pass them into a shell command and use the shell's parameter substitution facility to modify the names, like sh -c 'for f; do somecommand "$f" "${f%.*}.al"; done' sh {} To ...


0

Replacing in files Your command isn't reliable for several reasons: it excludes all paths containing .git as a substring, it doesn't work with paths containing whitespace or \'", it replaces input with any character between com and foo. The last problem is easily solved by adding a backslash before the dot. The problems with file names may or may not be an ...


1

1 For your first step, in your command example, you do not need the * because that is not filtering any file. What you do need is to filter .git, as this: $ find . -name '.git' -prune -o -type f -print That will reject (-prune) any directory exactly named .git and everything inside it. That removes the need of grep -v ".git". The sed could not be ...


0

Use sed for file in */*.ext; do ext2=`echo $file | sed 's/.ext/.ext2/'` mv $file $ext2 done


1

You can use the -printf function of find to construct your commands: find /tmp -name "*.ext" -printf "mv %p %h/new_name.ext" mv /tmp/foo.ext /tmp/new_name.ext When you surround the command with $(), the commands will be executed: $(find /tmp -name "*.ext" -printf "mv %p %h/new_name.ext") find /tmp -name "*.ext" /tmp/new_name.ext Update: The above ...



Top 50 recent answers are included