Handle files with space in filename and output file names

spaces in filename linux
linux find files with spaces in name
bash filename with spaces variable
grep filename with spaces
space in file name ubuntu
dealing with file names with spaces in linux
spaces in filename windows
linux list files with spaces in name

I need to write a Bash script that achieve the following goals:

1) move the newest n pdf files from folder 1 to folder 2;

2) correctly handles files that could have spaces in file names;

3) output each file name in a specific position in a text file. (In my actual usage, I will use sed to put the file names in a specific position of an existing file.)

I tried to make an array of filenames and then move them and do text output in a loop. However, the following array cannot handle files with spaces in filename:

pdfs=($(find -name "$DOWNLOADS/*.pdf" -print0 | xargs -0 ls -1 -t | head -n$NUM))

Suppose a file has name "Filename with Space". What I get from the above array will have "with" and "Space" in separate array entries. I am not sure how to avoid these words in the same filename being treated separately. Can someone help me out?

Thanks!

-------------Update------------

Sorry for being vague on the third point as I thought I might be able to figure that out after achieving the first and second goals.

Basically, it is a text file that have a line start with "%comment" near the end and I will need to insert the filenames before that line in the format "file=PATH". The PATH is the folder 2 that I have my pdfs moved to.


find downloads -name "*.pdf" -printf "%T@ %p\0" |
sort -z -t' ' -k1 -n |
cut -z -d' ' -f2- |
tail -z -n 3
  1. find all *.pdf files in downloads
  2. for each file print it's modifition date %T with the format specifier @ that means seconds since epoch with fractional part, then print space, filename and separate with \0
  3. Sort the null separated stream using space as field separator using only first field using numerical sort
  4. Remove the first field from the stream, ie. creation date, leaving only filenames.
  5. Get the count of the newest files, in this example 3 newest files, by using tail. We could also do reverse sort and use head, no difference.
  6. Don't use ls in scripts. ls is for nice formatted output. You could do xargs -0 stat --printf "%Y %n\0" which would basically move your script forward, as ls isn't meant to be used for scripts. Just that I couldn't make stat output fractional part of creation date.

As for the second part, we need to save the null delimetered list to a file

find downloads ........ >"$tmp"

and then:

str='%comment'
{
    grep -B$((2**32)) -x "$str" "$out" | grep -v "$str"
    # I don't know what you expect to do with newlines in filenames, but I guess you don't have those
    cat "$tmp" | sed -z 's/^/file=/' | sed 's/\x0/\n/g'
    grep -A$((2**32)) -x "$str" "$out"
} | sponge "$out"

where output is the output file name

  1. assuming output file name is stored in variable "$out"
  2. filter all lines before the %comment and remove the line %comment itself from the file
  3. output each filename with file= on the beginning. I also substituted zeros for newlines.
  4. the filter all lines after %comment including %comment itself
  5. write the output for outfile. Remember to use a temporary file.
  6. Don't use pdf=$(...) on null separated inputs. You can use mapfile to store that to an array, as other answers provided.

Then to move the files, do smth like

<"$tmp" xargs -0 -i mv {} "$outdir"

or faster, with a single move:

{ cat <"$tmp"; printf "%s\0" "$outdir"; } | xargs -0 mv

or alternatively:

<"$tmp" xargs -0 sh -c 'outdir="$1"; shift; mv "$@" "$outdir"' -- "$outdir"

Live example at turorialspoint.

Looping through files with spaces in the names?, Better answer (also handles wildcards and newlines in file names) off to get the next file name, and runs the next loop, etc., until it reaches the end of output. However, most users will still have issues while trying to handle passing filenames with spaces in bash. This is because spaces are not considered the same in bash as they are in file names. Files with spaces in the name


You can achieve this using mapfile in conjunction with gnu versions of find | sort | cut | head that have options to operate on NUL terminated filenames:

mapfile -d '' -t pdfs < <(find "$DOWNLOADS/*.pdf" -name 'file*' -printf '%T@:%p\0' | 
sort -z -t : -rnk1 | cut -z -d : -f2- | head -z -n $NUM)

Commands used are:

  1. mapfile -d '': To read array with NUL as delimiter
  2. find: outputs each file's modification stamp in EPOCH + ":" + filename + NUL byte
  3. sort: sorts reverse numerically on 1st field
  4. cut: removes 1st field from output
  5. head: outputs only first $NUM filenames

How do I use find when the filename contains spaces?, The first of the following will feed the filenames to somecommand one at a of files (at which point you'll run into the shell's maximum number of arguments), but​  BASH for loop works nicely under UNIX / Linux / Windows and OS X while working on set of files. However, if you try to process a for loop on file name with spaces in them you are going to have some problem.


How to Read a Filename with Spaces in Linux, common in Linux to handle filename with spaces but sometimes files copied To create files with spaces in file names, run the command as shown To view the file execute the command below $ cat linoxide\ docs. Output. 2) correctly handles files that could have spaces in file names; 3) output each file name in a specific position in a text file. (In my actual usage, I will use sed to put the file names in a specific position of an existing file.) I tried to make an array of filenames and then move them and do text output in a loop.


Bash v4 has an option globstar, after enabling this option, we can use ** to match zero or more subdirectories.

mapfile is a built-in command, which is used for reading lines into an indexed array variable. -t option removes a trailing newline.

shopt -s globstar
mapfile -t pdffiles < <(ls -t1 **/*.pdf | head -n"$NUM")

typeset -p pdffiles

for f in "${pdffiles[@]}"; do
  echo "==="
  mv "${f}" /dest/path
  sed "/^%comment/i${f}=/dest/path" a-text-file.txt
done

How to Manipulate Filenames Having Spaces and Special, We come across files and folders name very regularly. In most of the cases Sample Output. touch: invalid option Treat file name having Square Brackets as normal files and you need not take extra care of it. $ touch [12.txt]  In fact, if you carefully look at the output, you can see that command-line has treated the file name as three different files due to the three spaces that are present in the file name. So how can we overcome this ? Well, you can add backslashes as mentioned before and below is the correct command using that. sudo cp Data\ backup\ 2.tar /media/pen


How can I handle spaces in file names when using xargs on find , -print0 True; print the full file name on the standard output, followed by a null files, but the command line is built by appending each selected file name at the  Alpha-Numeric file name are pretty common and very widely used, but this is not the case when we have to deal with file/folder name that has special characters in them. Note : We can have files of any type but for simplicity and easy implementation we will be dealing with Text file ( .txt ), throughout the article.


Work the Shell, Spaces in filenames can cause great trouble in shell scripts! The shell can deal with these filenames if they're simple enough, and the for flat-file text database files), but it still doesn't really solve our filename problem. Hello I've got a certain no. of files in a directory whose names I'm reading and redirecting into a temporary text file using the command below: ls -l | grep ^- | awk '{print $9}'However, whenever the file names contain spaces the above command considers only the part of the file name up to


Making BASH script `for` handle filenames with spaces (or , You can make this proof against files with newlines in their names, if you wish, Set your find to output your field delimiter after the %P and set your IFS appropriately. I picked semi-colon since it's highly unlikely to found in your filenames. To to use files with spaces you can either use the escape character or youse the double quotes. \ is called escape character, used to not expansion of space, so now bash read the space as part of file name. Or you can use: Now to rename files, it's so easy to rename all files with spaces and replace space with underscore: